I am trying to go through SICP using Racket and Project Euler as reference for practice. This question is in regards to problem 4 (https://projecteuler.net/problem=4), hence:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
I am currently still on Chapter 1 (SICP) and loops have not been covered yet, as I see most solutions use. My code runs out of memory every time I try to execute (I have been stuck on this for hours - https://github.com/polila/Project-Euler/commits?author=polila&since=2018-03-19T04:00:00Z&until=2018-03-20T04:00:00Z) LOL.
What I am trying to do is use a recursive procedure by the process of linear iteration (at least that's what I think) - so in my mind it was something like this, where a and b are the max limit of n-digit:
(largest-palindrome a b max)
( 999 999 0)
( 999 998 0)
( 999 997 0)
( . . .)
( . . .)
( 999 99 x)
( 998 998 x)
( 998 997 x)
( 998 996 x)
( . . x)
( 100 100 x)
I realize that I wouldn't have to go all the way to the minimum range but even for small test cases such as 2-digit palindromes with the range of [90,99] it still doesn't execute. But here is my code, where am I going wrong??????????
#lang racket
(define (exp a b)
(define (iter product count)
(if (= count b)
product
(iter (* a product) (+ count 1))))
(if (= b 0)
1
(iter a 1)))
(define (palindrome? ab)
(define (length ab)
(define (iter n count)
(if (= n 0)
count
(iter (floor (/ n 10)) (+ count 1))))
(iter ab 0))
(define (check-symmetry ab left right)
(if (> left right)
(if (= (floor (/ (modulo ab (exp 10 left)) (exp 10 (- left 1))))
(floor (/ (modulo ab (exp 10 right)) (exp 10 (- right 1)))))
(check-symmetry ab (- left 1) (+ right 1))
#f)
#t))
(check-symmetry ab (length ab) 1))
(define (largest-palindrome a b max)
(if (> b 100)
(if (and (palindrome? (* a b)) (< max (* a b)))
(largest-palindrome a (- b 1) (* a b))
(largest-palindrome a (- b 1) max))
(largest-palindrome (- a 1) (- a 1) (* a b)))
(if (< a 100)
max
0))
You have the right general idea of looking at multiples starting at 999x999 all the way down to 100x100. You can improve efficiency on this method by terminating b whenever a x b is a palindrome, such that you don't test for palindromes in a x b-1 etc. since those products will be smaller in value than a x b.
What this looks like is:
999 x 999 -- not palindrome
999 x 998 -- not palindrome
|
995 x 583 -- palindrome (if current palindrome < this, save this value)
994 x 994 -- not palindrome (Notice the jump here instead of testing 995 x 582)
994 x 993 -- not palindrome
|
994 x 100 -- not palindrome
993 x 993 -- not palindrome
|
993 x 913 -- palindrome (if current < this, save this value)
992 x 992 -- not palindrome
|
100 x 100 -- not palindrome (hit base case and return current palindrome)
In your implementation of largest-palindrome, the first if-statement, ie. (if (> b 100) ...), is dead code. Moreover, the recursive steps in that if statement also have no base case(s), hence why you run out of memory every time as a result of the infinite recursion.
You can simplify much of your code. For example, consider the following palindrome? predicate that checks whether a number is equal to its digits reversed:
(define (palindrome? n)
(define (in-reverse n acc)
(if (< n 10)
(+ (* acc 10) n)
(in-reverse (quotient n 10)
(+ (* acc 10)
(remainder n 10)))))
(= n (in-reverse n 0)))
ie.
(palindrome? 1001)
=> #t
(palindrome? 1010)
=> #f
You can then implement largest-palindrome using this predicate:
;; largest-palindrome: Finds the largest palindrome that is a
;; multiple of two numbers, each of which has n digits.
(define (largest-palindrome n)
(define low (expt 10 (sub1 n))) ;; if n = 3, low = 100
(define high (sub1 (expt 10 n))) ;; if n = 3, high = 999
(define (largest a b mymax low high)
(define prod (* a b))
(cond
((< a low) mymax)
((or (< b low)
(< prod mymax))
(largest (sub1 a) (sub1 high) mymax low (sub1 high)))
((and (> prod mymax)
(palindrome? prod))
(largest (sub1 a) (sub1 high) prod b (sub1 high)))
(else
(largest a (sub1 b) mymax low high))))
(largest high high 0 low high))
this works for various values of n:
(largest-palindrome 3)
=> 906609
(largest-palindrome 5)
=> 9966006699
(largest-palindrome 7)
=> 99956644665999
Related
I want to write a function in Racket which takes an amount of money and a list of specific bill-values, and then returns a list with the amount of bills used of every type to make the given amount in total. For example (calc 415 (list 100 10 5 2 1)) should return '(4 1 1 0 0).
I tried it this way but this doesn't work :/ I think I haven't fully understood what you can / can't do with set! in Racket, to be honest.
(define (calc n xs)
(cond ((null? xs) (list))
((not (pair? xs))
(define y n)
(begin (set! n (- n (* xs (floor (/ n xs)))))
(list (floor (/ y xs))) ))
(else (append (calc n (car xs))
(calc n (cdr xs))))))
Your procedure does too much and you use mutation which is uneccesary. If you split the problem up.
(define (calc-one-bill n bill)
...)
;; test
(calc-one-bill 450 100) ; ==> 4
(calc-one-bill 450 50) ; ==> 9
Then you can make:
(define (calc-new-n n bill amount)
...)
(calc-new-n 450 100 4) ; ==> 50
(calc-new-n 450 50 9) ; ==> 0
Then you can reduce your original implememntation like this:
(define (calc n bills)
(if (null? bills)
(if (zero? n)
'()
(error "The unit needs to be the last element in the bills list"))
(let* ((bill (car bills))
(amount (calc-one-bill n bill)))
(cons amount
(calc (calc-new-n n bill amount)
(cdr bills))))))
This will always choose the solution with fewest bills, just as your version seems to do. Both versions requires that the last element in the bill passed is the unit 1. For a more complex method, that works with (calc 406 (list 100 10 5 2)) and that potentially can find all combinations of solutions, see Will's answer.
This problem calls for some straightforward recursive non-deterministic programming.
We start with a given amount, and a given list of bill denominations, with unlimited amounts of each bill, apparently (otherwise, it'd be a different problem).
At each point in time, we can either use the biggest bill, or not.
If we use it, the total sum lessens by the bill's value.
If the total is 0, we've got our solution!
If the total is negative, it is invalid, so we should abandon this path.
The code here will follow another answer of mine, which finds out the total amount of solutions (which are more than one, for your example as well). We will just have to mind the solutions themselves as well, whereas the code mentioned above only counted them.
We can code this one as a recursive-backtracking procedure, calling a callback with each successfully found solution from inside the deepest level of recursion (tantamount to the most deeply nested loop in the nested loops structure created with recursion, which is the essence of recursive backtracking):
(define (change sum bills callback)
(let loop ([sum sum] [sol '()] [bills bills]) ; "sol" for "solution"
(cond
((zero? sum) (callback sol)) ; process a solution found
((< sum 0) #f)
((null? bills) #f)
(else
(apply
(lambda (b . bs) ; the "loop":
;; 1. ; either use the first
(loop (- sum b) (cons b sol) bills) ; denomination,
;; 2. ; or,
(loop sum sol bs)) ; after backtracking, don't!
bills)))))
It is to be called through e.g. one of
;; construct `the-callback` for `solve` and call
;; (solve ...params the-callback)
;; where `the-callback` is an exit continuation
(define (first-solution solve . params)
(call/cc (lambda (return)
(apply solve (append params ; use `return` as
(list return)))))) ; the callback
(define (n-solutions n solve . params) ; n assumed an integer
(let ([res '()]) ; n <= 0 gets ALL solutions
(call/cc (lambda (break)
(apply solve (append params
(list (lambda (sol)
(set! res (cons sol res))
(set! n (- n 1))
(cond ((zero? n) (break)))))))))
(reverse res)))
Testing,
> (first-solution change 406 (list 100 10 5 2))
'(2 2 2 100 100 100 100)
> (n-solutions 7 change 415 (list 100 10 5 2 1))
'((5 10 100 100 100 100)
(1 2 2 10 100 100 100 100)
(1 1 1 2 10 100 100 100 100)
(1 1 1 1 1 10 100 100 100 100)
(5 5 5 100 100 100 100)
(1 2 2 5 5 100 100 100 100)
(1 1 1 2 5 5 100 100 100 100))
Regarding how this code is structured, cf. How to generate all the permutations of elements in a list one at a time in Lisp? It creates nested loops with the solution being accessible in the innermost loop's body.
Regarding how to code up a non-deterministic algorithm (making all possible choices at once) in a proper functional way, see How to do a powerset in DrRacket? and How to find partitions of a list in Scheme.
I solved it this way now :)
(define (calc n xs)
(define (calcAssist n xs usedBills)
(cond ((null? xs) usedBills)
((pair? xs)
(calcAssist (- n (* (car xs) (floor (/ n (car xs)))))
(cdr xs)
(append usedBills
(list (floor (/ n (car xs)))))))
(else
(if ((= (- n (* xs (floor (/ n xs)))) 0))
(append usedBills (list (floor (/ n xs))))
(display "No solution")))))
(calcAssist n xs (list)))
Testing:
> (calc 415 (list 100 10 5 2 1))
'(4 1 1 0 0)
I think this is the first program I wrote when learning FORTRAN! Here is a version which makes no bones about using everything Racket has to offer (or, at least, everything I know about). As such it's probably a terrible homework solution, and it's certainly prettier than the FORTRAN I wrote in 1984.
Note that this version doesn't search, so it will get remainders even when it does not need to. It never gets a remainder if the lowest denomination is 1, of course.
(define/contract (denominations-of amount denominations)
;; split amount into units of denominations, returning the split
;; in descending order of denomination, and any remainder (if there is
;; no 1 denomination there will generally be a remainder).
(-> natural-number/c (listof (integer-in 1 #f))
(values (listof natural-number/c) natural-number/c))
(let handle-one-denomination ([current amount]
[remaining-denominations (sort denominations >)]
[so-far '()])
;; handle a single denomination: current is the balance,
;; remaining-denominations is the denominations left (descending order)
;; so-far is the list of amounts of each denomination we've accumulated
;; so far, which is in ascending order of denomination
(if (null? remaining-denominations)
;; we are done: return the reversed accumulator and anything left over
(values (reverse so-far) current)
(match-let ([(cons first-denomination rest-of-the-denominations)
remaining-denominations])
(if (> first-denomination current)
;; if the first denomination is more than the balance, just
;; accumulate a 0 for it and loop on the rest
(handle-one-denomination current rest-of-the-denominations
(cons 0 so-far))
;; otherwise work out how much of it we need and how much is left
(let-values ([(q r)
(quotient/remainder current first-denomination)])
;; and loop on the remainder accumulating the number of bills
;; we needed
(handle-one-denomination r rest-of-the-denominations
(cons q so-far))))))))
I'm trying to create a Division function using only subtraction. What I have so far is enough to handle positive numbers. What keeps tricking me up is handling it for negative numbers. I can go ahead and just grab the absolute value of x and y and it works perfectly, but then my answer can never be negative. Anyone here whose had to do something similar before?
(define Divide (lambda (a b c)
(if (> a 0)
(Divide (- a b) b (+ c 1))
c
)
)
)
You can assign the product of sign values of a and b to a variable, then deal with only absolute values of both a and b while doing the recursion. Output then becomes the product of c and the sign variable as (* c sign). Consider the following:
(define (divide num denom)
(let div ([n num]
[d denom]
[acc 0]
[sign 1])
(cond
[(< n 0)
(div (- n) d acc (- sign))]
[(< d 0)
(div n (- d) acc (- sign))]
[(< n d)
(* sign acc)]
[else
(div (- n d) d (add1 acc) sign)])))
For example,
> (divide 10 7)
1
> (divide -10 7)
-1
> (divide -10 -7)
1
> (divide 10 -7)
-1
Note that if you use the condition (if (> a 0) ... instead of (if (>= a b) ..., then you add an extra step in your recursion, which is why using your function, (Divide 10 7 0) outputs 2.
In cases like this you often want to define an auxiliary function that the main function calls after massaging the data:
(define (Divide a b)
(define (go a b c)
(if (> a 0)
(go (- a b) b (+ c 1))
c))
(cond
[(and (> a 0) (> b 0))
(go a b 0)]
[(and (< a 0) (< b 0))
(go (- a) (- b) 0)]
[(< a 0)
(- (go (- a) b 0))]
[(< b 0)
(- (go a (- b) 0))]))
I have found a problem that it says it should be solved by using recursion. The question is that given a certain number it should count the number of 8s that are present in it, but if two 8s are one next to another it should be counted as double. For example:
48 should return 1
4881 should return 4
8818 should return 5
I have made the following program in Scheme:
(define (count n)
(if (= n 0)
0
(begin
(if (= (remainder n 100) 88)
2
(begin
(if (= (remainder n 10) 8)
1
0))
)
(+ (count (quotient n 10))))))
The problem is that everytime I run it returns 0, what am I missing? I do not want to use lists or set! for using an auxiliar variable. Any help?
You have to keep iterating whenever you find a match, and the sums don't seem right. Also, instead of nesting ifs it's better to use cond, like this:
(define (count n)
(cond ((= n 0) 0)
((= (remainder n 100) 88)
(+ 4 (count (quotient n 100))))
((= (remainder n 10) 8)
(+ 1 (count (quotient n 10))))
(else
(+ (count (quotient n 10))))))
It works with your examples:
(count 48)
=> 1
(count 4881)
=> 4
(count 8818)
=> 5
It would be better to count scans of 8s in a helper and keep a current number of hits and a total tally for previous scans.
(define (funny-eights n)
(define (aux n cur total)
(cond ((= (remainder n 10) 8)
(aux (quotient n 10) (+ cur 1) total))
((> cur 1)
(aux (quotient n 10) 0 (+ total (* 2 cur))))
((= cur 1)
(aux (quotient n 10) 0 (+ total cur)))
((> n 0)
(aux (quotient n 10) 0 total))
(else
total)))
(aux n 0 0))
(funny-eights 488838288) ; ==> 11 or 3*2 + 1 + 2*2
I need some help to implement a function that receives a number and returns the number of bits that would have been required to be “on” in order to represent the input number in binary base.
For example, the number 5 is represented as 101 in binary and therefore requires two bits to be “on”.
Example:
(numOfBitsOn 5) will return 2 because 5 in binary is 101
(numOfBitsOn 101) will return 4 because 101 in binary is 1100101
The function must be written as tail recursion.
This is m first time learning Scheme. Up to now this is all I wrote:
(define (numOfBitsOn number)
(define (numOfBitsOn-2 number acc)
(cond ((eq? number 0)acc)
(not(eq? (modulo number 2)0) (+ acc 1))
(numOfBitsOn-2 (/ number 2) acc))))
And it gives me that:
begin (possibly implicit): no expression after a sequence of internal definitions in: (begin (define (numofbitson-2 number acc) (cond ((eq? number 0) acc) (not (eq? (modulo number 2) 0) (+ acc 1)) (numofbitson-2 (number) acc))))
I'm sure it doesn't even close to the solution =\
Can you help me please?
Thanks!
(define (slow-popcount n)
(do ((n n (quotient n 2))
(count 0 (+ count (modulo n 2))))
((zero? n) count)))
So, I'm fiddling with some basic maths, and I wanted a function to convert between bases.
I wrote this function:
(define (convert-base from to n)
(let f ([n n])
(if (zero? n)
n
(+ (modulo n to) (* from (f (quotient n to)))))))
Which works for all my personal tests < base 10 and would as far as I can imagine function perfectly fine for tests > base 10 if I just added support for additional digits.
What's confusing me is that when I tried to make the function tail-recursive, I ended up with this mess (I've added some spacing for SO's benefit, because my code is not often clear or pretty):
;e.g. 10 2 10 should output 1010, 10 8 64 should output 100 etc.
(define (convert-base-tail from to n)
(let f ([n n]
[acc 0]
[zeros 0])
(begin (printf "n is ~a. acc is ~a. zeros are ~a.\n" n acc zeros)
(cond [(zero? n) (let exp
([x acc]
[shft zeros])
(if (zero? shft)
x
(exp (* x 10) (- shft 1))))]
[(zero? (modulo n to))
(if (zero? acc)
(f (quotient n to) (* acc from) (add1 zeros))
(f (quotient n to) (* acc from) zeros))]
[else (f (quotient n to) (+ (* acc from) (modulo n to)) zeros )]))))
My question is, essentially, why is the tail-recursive function so much more complicated? Is it inevitable, due to the nature of the problem, or is it due to an oversight on my part?
It isn't, really:
(define (convert-base from to n)
(let f ([n n] [mul 1] [res 0])
(if (zero? n)
res
(f (quotient n to) (* mul from) (+ res (* mul (modulo n to)))))))
Testing
> (convert-base-y 10 2 10)
1010
> (convert-base-y 10 8 64)
100