Approximate overview
string->integerA map of our classroom, more or less.
1 2 3 4
+-+-----+-----+-----+-----+-+
0 | | | | | |o| 40
+-+-----+-----+-----+-----+-+ 39
5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20
+-----+-----+-----+-----+
S | | | | | 38
C +-----+-----+-----+-----+ 37
R 21 22 23 24 25 26 27 28
E
E 29 30 31 32 33 34 35 36
N +-----+-----+-----+-----+-----+-----+
| | | | | | |
Events
Other good things
An exercise in decomposition, alternate thinking, and more.
I have to convert “4251” into the number 4251.
How do I do that by hand?
Things I may have to do
How do I break that apart?
reverse)"5" (or #\5) -> 5(define digit->integer
(lambda (ch)
(- (char->integer ch) (char->integer #\0))))
There are three ways I know of to get individual digits.
list-ref (gives me a character)substring (gives me a string)string->listTo use list-ref or substring, we’ll need a way to loop (in Scheme,
the looping mechanism is called “recursion” and you’ll start learning
it in two weeks).
So we’ll use string->list. Let’s check it out.
> (string->list "4251")
'(#\4 #\2 #\5 #\1)
For normal indexing, that’s backwards. Let’s reverse it.
> (reverse (string->list "4251"))
'(#\1 #\5 #\2 #\4)
> (list-ref (reverse (string->list "4251")) 0)
#\1
> (list-ref (reverse (string->list "4251")) 1)
#\5
> (list-ref (reverse (string->list "4251")) 2)
#\2
> (list-ref (reverse (string->list "4251")) 4)
. . list-ref: index too large for list
index: 4
in: '(#\1 #\5 #\2 #\4)
> (list-ref (reverse (string->list "4251")) 3)
#\4
I have to convert each of those to a digit. map
> (map digit->integer (reverse (string->list "4251")))
'(1 5 2 4)
Now I need powers of ten for the multiplication.
(define ten-to-the
(lambda (n)
(expt 10 n)))
Let’s check it
> (ten-to-the 0)
1
> (ten-to-the 1)
10
> (ten-to-the 2)
100
> (ten-to-the 3)
1000
> (ten-to-the 4)
10000
Yay!
But I need those in a list. For this case, I want the list '(1 10 100 1000).
I use map to make lists.
> (map ten-to-the '(0 1 2 3))
'(1 10 100 1000)
I have the digits. I have the multipliers. I still don’t know how
to do a loop. But I do know how to work with lists. map.
> (map * '(1 5 2 4) '(1 10 100 1000))
'(1 50 200 4000)
How did I compute those?
> (map *
(reverse (map digit->integer (string->list "4251")))
(map ten-to-the '(0 1 2 3)))
'(1 50 200 4000)
Now I need to add them up. map?
> (map + '(1 50 200 4000))
'(1 50 200 4000)
I’m not trying to add two lists together. I’m trying to combine all
of the elements of a list into a single value. Not map (list to a
list). Is it filter? Also a list to a list. reduce or apply.
[That’s an important thing to think about.]
> (reduce + '(1 50 200 4000))
4251
Yay! Get all of the code there.
> (reduce + (map *
(reverse (map digit->integer (string->list "4251")))
(map ten-to-the '(0 1 2 3))))
4251
Now we’re ready to generalize.
(define digits->integer
(lambda (str)
(reduce + (map *
(reverse (map digit->integer (string->list str)))
(map ten-to-the '(0 1 2 3))))))
Need to document
;;; (digits->integer str) -> integer?
;;; str : string? (consisting only of digits)
;;; Convert a string to the corresponding integer.
Maybe I should try it on numbers that don’t have four digits.
> (digits->integer "123")
. . map: all lists must have same size
first list length: 3
other list length: 4
procedure: #<procedure:*>
Whoops! I can’t use '(0 1 2 3). I can use the range function.
> (range 0 4)
'(0 1 2 3)
(define digits->integer
(lambda (str)
(reduce + (map *
(reverse (map digit->integer (string->list str)))
(map ten-to-the (range (string-length str)))))))
> (digits->integer "123")
123
> (digits->integer "21334623412343212")
21334623412343212
The mentors say it looks good.
Some definitions
(define f
(lambda (x y)
(string-append x "-" (string-reverse x))))
(define g
(lambda (x y)
(string-append (f x x) " " (f y x))))
(define h
(lambda (x y)
(string-append (g x y) "&" (g y x))))
Tracing policies
And the trace
h("foo" "bar")
-->
When will we get MP2 back?
Soon, I expect.