I am a Common Lisp beginner, but not so in C++.
There's a simple C++ program that I am trying to mirror in CL (see Pollard's Rho algorithm variant example in C++
).
The C++ program runs without errors. One requirement is that all the outputs from both the programs must match.
C++ version
int gcd(int a, int b) {
int remainder;
while (b != 0) {
remainder = a % b;
a = b;
b = remainder;
}
return a;
}
int prime () {
int n = 10403, x_fixed = 2, cycle_size = 2, x = 2, factor = 1;
while (factor == 1) {
for (int count=1;count <= cycle_size && factor <= 1;count++) {
x = (x*x+1)%n;
factor = gcd(x - x_fixed, n);
}
cycle_size *= 2;
x_fixed = x;
}
cout << "\nThe factor is " << factor;
return 0;
}
Common Lisp version
Here is what I've come up with. The debugging is giving me nightmares, yet I tried a lot many times and stepped through the entire code, still I have no idea where I have gone wrong :(
(defun prime ()
(setq n 10403)
(setq x_fixed 2)
(setq cycle_size 2)
(setq x 2)
(setq factor 1)
(setq count 1)
(while_loop))
(defun while_loop ()
(print
(cond ((= factor 1)
(for_loop)
(setf cycle_size (* cycle_size 2))
(setf x_fixed x)
(setf count 1)
(while_loop))
((/= factor 1) "The factor is : ")))
(print factor))
(defun for_loop ()
(cond ((and (<= count cycle_size) (<= factor 1))
(setf x (rem (* x (+ x 1)) n))
(setf factor (gcd (- x x_fixed) n)))
((or (<= count cycle_size) (<= factor 1))
(setf count (+ count 1)) (for_loop))))
Notes
I named all variables and constants the same as in the C++ version.
I took half a day to decide whether or not to ask this question
If my Common Lisp code looks funny or silly you free to not-help
You need to define local variables.
A basic translation of the C code would look similar to this:
(defun my-gcd (a b)
(let ((remainder 0))
(loop while (/= b 0) do
(setf remainder (mod a b)
a b
b remainder))
a))
or with type declarations:
(defun my-gcd (a b)
(declare (integer a b))
(let ((remainder 0))
(declare (integer remainder))
(loop while (/= b 0) do
(setf remainder (mod a b)
a b
b remainder))
a))
The integer data type in Common Lisp is unbounded - unlike an int in C++.
You really need to do more reading on Common Lisp. It has all the basic imperative constructs of C++, so there's no need to go through the contortions you have just to translate a simple algorithm. See for example Guy Steele's classic, available for free.
Here is a more reasonable and idiomatic trans-coding:
(defun prime-factor (n &optional (x 2))
(let ((x-fixed x)
(cycle-size 2)
(factor 1))
(loop while (= factor 1)
do (loop for count from 1 to cycle-size
while (<= factor 1)
do (setq x (rem (1+ (* x x)) n)
factor (gcd (- x x-fixed) n)))
(setq cycle-size (* 2 cycle-size)
x-fixed x)))
factor))
(defun test ()
(prime-factor 10403))
Related
If i have a scheme code that generates the following result: (i'm using cons)
'((1 . 0) . 0)
How can i take this, and just simply display 100 as if it were just one integer number and not a list presented with those dots and parenthesis?
Thanks!
EDIT:
my full code:
(define (func X)
(if ( <= X 3 )
X
(cons (modulo X 4) (func(floor(/ X 4)) ))
))
If I understand correctly, you're trying to convert a number from base 10 to base 4, and then display it as a number, but there are several problems with your implementation.
You're building a list as output - but that's not what you want, you want a number. Also, you're traversing the input in the wrong order, and that's not the correct way to find the quotient between two numbers. Perhaps this will help:
(define (func X)
(let loop ((n X) (acc 0) (mult 1))
(if (< n 4)
(+ (* mult n) acc)
(loop (quotient n 4)
(+ (* mult (modulo n 4)) acc)
(* mult 10)))))
Alternatively, you could output a string to stress the fact that the output is not in base 10:
(define (func X)
(let loop ((n X) (acc ""))
(if (< n 4)
(string-append (number->string n) acc)
(loop (quotient n 4)
(string-append (number->string (modulo n 4)) acc)))))
It'll work as expected:
(func 16)
=> 100
Oscar Lopez's answer is excellent. I can't help adding that this problem doesn't need the "loop" construct:
;; translate a string to a base-4 string.
(define (func n)
(cond [(< n 4) (number->string n)]
[else (string-append (func (quotient n 4))
(number->string (modulo n 4)))]))
When reaching my recursion cases, I use list to append the future result with the current one, but I end up with a nested list because of recursion. This causes an error when I have a number that causes recursion for more than five times.
Any ideas how I can get results in a single plain non-nested list, e.g.:
CL-USER 100 : 8 > (BINARY_LIST 4)
(1 0 0)
Code & Example output:
CL-USER 99 : 8 > (defun binary_list (i)
(COND
((= i 0) 0)
((= i 1) 1)
((= (mod i 2) 0) (list (binary_list (truncate i 2)) 0))
(t (list (binary_list (truncate i 2)) 1))
)
)
BINARY_LIST
CL-USER 100 : 8 > (BINARY_LIST 4)
((1 0) 0)
CL-USER 101 : 8 > (BINARY_LIST 104)
((((# 1) 0) 0) 0)
You are almost there. All you need to do is to replace list with nconc:
(defun binary-list (n)
(cond ((= n 0) (list 0))
((= n 1) (list 1))
(t (nconc (binary-list (truncate n 2)) (list (mod n 2))))))
You can avoid calling both truncate and mod by collecting both values in integer division:
(defun binary-list (n)
(assert (>= n 0))
(multiple-value-bind (q r) (floor n 2)
(if (zerop q)
(list r)
(nconc (binary-list q) (list r)))))
Note that this algorithm is quadratic because nconc has to traverse the result on each iteration. This can be avoided by passing an accumulator:
(defun binary-list (n &optional acc)
(assert (>= n 0))
(multiple-value-bind (q r) (floor n 2)
(if (zerop q)
(cons r acc)
(binary-list q (cons r acc)))))
Now we have a tail-recursive function which can be compiled to iteration by a modern compiler.
One more optimization trick you could use (which, in fact, should be done by the compiler - try disassemble to check!) is using ash and logand instead of the much more general and expensive floor:
(defun binary-list (n &optional acc)
(cond ((zerop n) (or acc (list 0)))
((plusp n)
(binary-list (ash n -1) (cons (logand 1 n) acc)))
(t (error "~S: non-negative argument required, got ~s" 'binary-list n))))
Incidentally, lispers usually use dash instead of underscores in symbols, so your binary_list should be binary-list if you do not want to offend our tender aesthetics.
this seems to me to be the most direct, least roundabout manner to achieve the desired results every time:
(defun mvp-binary-from-decimal (n r)
(if (zerop n)
r
(multiple-value-bind (a b)
(floor n 2)
(mvp-binary-from-decimal a (cons b r)))))
(defun binary-from-decimal (n)
(if (and (numberp n) (plusp n))
(mvp-binary-from-decimal n '())
(if (eql n 0) '(0) nil)))
tested in slime, sbcl, clisp - used as follows:
CL-USER> (binary-from-decimal 100)
(1 1 0 0 1 0 0)
CL-USER> (binary-from-decimal 10)
(1 0 1 0)
CL-USER> (binary-from-decimal 0)
(0)
there are some advanced reasons as to why this might be the most desirable manner in which to implement such functionality, but for now, suffice to say that it is clean, polite, readable and always works.
I have 2 numbers let's say number1=5 and number2=3 and I want to create a list in this form
((1(1 2 3)) (2(1 2 3)) (3(1 2 3)) (4(1 2 3)) (5(1 2 3)))
So the number1 indicates the number of the elements in the list and number2 indicates the total elements that will be as the second part of every element..
I have smth like this untill now
(define mylist '())
(define (pushlist item item2)
(do ((j 1 (+ j 1))) ((> j item2))
(set! mylist(list mylist (list item j)))))
(define (createlist number number2)
(do ((j 1 (+ j 1))) ((> j number))
(pushlist j number2)
))
(createlist 5 3)
Unfortunately it doesn't work.. It doesn't give the result I want.. It gives me this (((((((((((((((() (1 1)) (1 2)) (1 3)) (2 1)) (2 2)) (2 3)) (3 1)) (3 2)) (3 3)) (4 1)) (4 2)) (4 3)) (5 1)) (5 2)) (5 3))
There are many ways to solve this problem - for example, using explicit recursion, or using higher-order procedures. Your approach is not recommended, in Scheme you should try to avoid thinking about loops and mutation operations. Although it is possible to write such a solution, it won't be idiomatic. I'll try to explain how to write a more idiomatic solution, using explicit recursion first:
; create a list from i to n
(define (makelist i n)
(if (> i n)
'()
(cons i (makelist (add1 i) n))))
; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist i m n)
(if (> i m)
'()
(cons (list i (makelist 1 n))
(makenumlist (add1 i) m n))))
; call previous functions
(define (createlist number1 number2)
(makenumlist 1 number1 number2))
Now, an even more idiomatic solution would be to use higher-order procedures. This will work in Racket:
; create a list from i to n
(define (makelist n)
(build-list n add1))
; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist m n)
(build-list m
(lambda (i)
(list (add1 i) (makelist n)))))
; call previous functions
(define (createlist number1 number2)
(makenumlist number1 number2))
See how we can avoid explicit looping? that's the Scheme way of thinking, the way you're expected to solve problems - embrace it!
I don't think that your pushlist procedure is doing what you you expect it to.
(define (pushlist item item2)
(do ((j 1 (+ j 1)))
((> j item2))
(set! mylist (list mylist (list item j)))))
If you have a list (x y z) and you want to push a new value v into it, you'd do
(set! lst (cons v lst))
because (cons v (x y z)) == (v x y z). By doing
(set! mylist (list mylist (list item j)))
you're making mylist always have exactly two elements, where the first is a deeper and deeper nested list. Óscar López's answer gives a more idiomatic approach to this problem. Here's a similar idiomatic approach:
(define (range n)
; returns a list (1 ... n)
(let rng ((n n) (l '()))
(if (zero? n)
l
(rng (- n 1) (cons n l)))))
If the sublists (1 ... n) can all be the same list (i.e., the actual list object is the same), then you can create it just once:
(define (createlist m n)
(let ((sublist (range n)))
(map (lambda (main)
(list main sublist))
(range m))))
Otherwise, if they need to be distinct, you can generate one for each of 1 ... m:
(define (createlist m n)
(map (lambda (main)
(list main (range n)))
(range m)))
I need a subroutine for my program written in scheme that takes an integer, say 34109, and puts it into a list with elements 3, 4, 1, 0, 9. The integer can be any length. Does anyone have a trick for this? I've thought about using modulo for every place, but I don't think it should be that complicated.
The simplest way I can think of, is by using arithmetic operations and a named let for implementing a tail-recursion:
(define (number->list num)
(let loop ((num num)
(acc '()))
(if (< num 10)
(cons num acc)
(loop (quotient num 10)
(cons (remainder num 10) acc)))))
Alternatively, you can solve this problem using string operations:
(define char-zero (char->integer #\0))
(define (char->digit c)
(- (char->integer c) char-zero))
(define (number->list num)
(map char->digit
(string->list (number->string num))))
This can be compressed into a single function, but I believe it's easier to understand if we split the problem in subparts as above.
(define (number->list num)
(map (lambda (c) (- (char->integer c) (char->integer #\0)))
(string->list
(number->string num))))
Anyway, the results are as expected:
(number->list 34109)
> '(3 4 1 0 9)
Something like this:
(define (num2list-helper num lst)
(cond ((< num 10) (cons num lst))
(else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))
(define (num2list num)
(num2list-helper num '()))
(num2list 1432)
As itsbruce commented you can hide helper function inside main one:
(define (num2list num)
(define (num2list-helper num lst)
(cond ((< num 10) (cons num lst))
(else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))
(num2list-helper num '()))
(num2list 1432)
to be continued...
I'm not a fan of manual looping, so here's a solution based on unfold (load SRFI 1 and SRFI 26 first):
(define (digits n)
(unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))
This returns an empty list for 0, though. If you want it to return (0) instead, we add a special case:
(define (digits n)
(case n
((0) '(0))
(else (unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))))
Of course, you can generalise this for other bases. Here, I implement this using optional arguments, so if you don't specify the base, it defaults to 10:
(define (digits n (base 10))
(case n
((0) '(0))
(else (unfold-right zero? (cut modulo <> base) (cut quotient <> base) n))))
Different Scheme implementations use different syntaxes for optional arguments; the above uses Racket-style (and/or SRFI 89-style) syntax.
I have created a very simple nested loop example and am struggling to write the equivalent Clojure code. I've been trying to do it by list comprehensions but cannot get the same answer. Any help appreciated.
public class Toy {
public static void main(String[] args) {
int maxMod = 0;
for (int i=0;i<1000;i++) {
for (int j=i;j<1000;j++) {
if ((i * j) % 13 == 0 && i % 7 == 0) maxMod = i * j;
}
}
System.out.println(maxMod);
}
}
Here's a list comprehension solution:
(last
(for [i (range 1000)
j (range 1000)
:let [n (* i j)]
:when (and (= (mod n 13) 0)
(= (mod i 7) 0))]
n))
In general, you want to use some sort of sequence operation (like dnolen's answer). However, if you need to do something that is not expressible in some combination of sequence functions, using the loop macro works as well. For this precise problem, dnolen's answer is better than anything using loop, but for illustrative purposes, here is how you would write it with loop.
(loop [i 0
max-mod 0]
(if (>= i 1000)
(println max-mod)
(recur (inc i)
(loop [j 0
max-mod max-mod]
(if (>= j 1000)
max-mod
(recur (inc j)
(if (and (= (mod (* i j) 13) 0)
(= (mod 1 7) 0))
(* i j)
max-mod)))))))
This is pretty much an exact translation of your given code. That said, this is obviously ugly, which is why a solution using for (or other similar functions) is preferred whenever possible.
List comprehensions create lists from other lists, but you want just a single value as result. You can create the input values (i and j) with a list comprehension, and then use reduce to get a single value from the list:
(reduce (fn [max-mod [i j]]
(if (and (zero? (mod (* i j) 13))
(zero? (mod i 7)))
(* i j)
max-mod))
0
(for [i (range 1000) j (range 1000)]
[i j]))