How to reverse integer in Prolog using tail-recursion? - recursion

I would like to make a predicat reverse(N,Result) in Prolog.
For example:
reverse(12345,Result).
Result = 54321.
I have to use tail-recursion. I can use *, +, - and divmod/4 and that's all.I can't use list.
I can reverse a number < 100 but I don't find how to finish my code, I can't complete my code to reverse integers bigger than 100 correctly.
reverse(N,N):-
N <10,
N>0.
reverse(N,Result):-
N > 9,
iter(N,0,Result).
iter(N,Ac,Result):-
N < 100, !,
divmod(N,10,Q,R),
R1 is R*10,
Result is Q + R1.
Can I have some help please ?
Thanks you in advance.

I suggest the use of CLP(FD), since it offers declarative reasoning over integer arithmetic and a lot of Prolog systems provide it. Concerning the digit-reversal, I recommend you take a look at entry A004086 in The On-Line Encyclopedia of Integer Sequences. In the paragraph headed FORMULA, you'll find, among others, the following formulae:
a(n) = d(n,0) with d(n,r) = if n=0 then r else d(floor(n/10),r*10+(n mod 10))
These can be translated into a predicates by adding an additional argument for the reversed number. First let's give it a nice declarative name, say digits_reversed/2. Then the relation can be expressed using #>/2, #=/2, (/)/2, +/2, mod/2 and tail-recursion:
:- use_module(library(clpfd)).
digits_reversed(N,X) :-
digits_reversed_(N,X,0).
digits_reversed_(0,R,R).
digits_reversed_(N,X,R) :-
N #> 0,
N0 #= N/10,
R1 #= R*10 + (N mod 10),
digits_reversed_(N0,X,R1).
Note that digits_reversed/2 correspond to a(n) and digits_reversed_/3 corresponds to d(n,r) in the above formulae. Now let's query the predicate with the example from your post:
?- digits_reversed(12345,R).
R = 54321 ;
false.
The predicate can also be used in the other direction, that is ask What number has been reversed to obtain 54321? However, since leading zeros of numbers are omitted one reversed number has infinitely many original numbers:
?- digits_reversed(N,54321).
N = 12345 ;
N = 123450 ;
N = 1234500 ;
N = 12345000 ;
N = 123450000 ;
N = 1234500000 ;
N = 12345000000 ;
N = 123450000000 ;
.
.
.
Even the most general query yields solutions but you'll get residual goals as an answer for numbers with more than one digit:
?- digits_reversed(N,R).
N = R, R = 0 ; % <- zero
N = R,
R in 1..9 ; % <- other one-digit numbers
N in 10..99, % <- numbers with two digits
N mod 10#=_G3123,
N/10#=_G3135,
_G3123 in 0..9,
_G3123*10#=_G3159,
_G3159 in 0..90,
_G3159+_G3135#=R,
_G3135 in 1..9,
R in 1..99 ;
N in 100..999, % <- numbers with three digits
N mod 10#=_G4782,
N/10#=_G4794,
_G4782 in 0..9,
_G4782*10#=_G4818,
_G4818 in 0..90,
_G4818+_G4845#=_G4842,
_G4845 in 0..9,
_G4794 mod 10#=_G4845,
_G4794 in 10..99,
_G4794/10#=_G4890,
_G4890 in 1..9,
_G4916+_G4890#=R,
_G4916 in 0..990,
_G4842*10#=_G4916,
_G4842 in 0..99,
R in 1..999 ;
.
.
.
To get actual numbers with the query above, you have to restrict the range of N and label it after the predicate has posted the arithmetic constraints:
?- N in 10..20, digits_reversed(N,R), label([N]).
N = 10,
R = 1 ;
N = R, R = 11 ;
N = 12,
R = 21 ;
N = 13,
R = 31 ;
N = 14,
R = 41 ;
N = 15,
R = 51 ;
N = 16,
R = 61 ;
N = 17,
R = 71 ;
N = 18,
R = 81 ;
N = 19,
R = 91 ;
N = 20,
R = 2 ;
false.

If for some reason you don't want a constraints based solution, or if you using a Prolog system not supporting constraints, an alternative solution is:
reverse_digits(N, M) :-
( integer(N) ->
reverse_digits(N, 0, M)
; integer(M),
reverse_digits(M, 0, N)
).
reverse_digits(0, M, M) :- !.
reverse_digits(N, M0, M) :-
N > 0,
R is N div 10,
M1 is M0 * 10 + N mod 10,
reverse_digits(R, M1, M).
This solution can be used with either argument bound to an integer and leaves no spurious choice-points:
?- reverse_digits(12345, M).
M = 54321.
?- reverse_digits(N, 12345).
N = 54321.
?- reverse_digits(12345, 54321).
true.
But note that this solution, unlike the constraints based solution, cannot be used as a generator of pairs of integers that satisfy the relation:
?- reverse_digits(N, M).
false.

reverseNumber(N,R):-reverse_acc(N,0,R).
reverse_acc(0,Acc,Acc).
reverse_acc(N,Acc,R):- C is N mod 10, N1 is N div 10,
Acc1 is Acc * 10 + C,
reverse_acc(N1, Acc1,R).

Related

Concatenation of binary representation of first n positive integers in O(logn) time complexity

I came across this question in a coding competition. Given a number n, concatenate the binary representation of first n positive integers and return the decimal value of the resultant number formed. Since the answer can be large return answer modulo 10^9+7.
N can be as large as 10^9.
Eg:- n=4. Number formed=11011100(1=1,10=2,11=3,100=4). Decimal value of 11011100=220.
I found a stack overflow answer to this question but the problem is that it only contains a O(n) solution.
Link:- concatenate binary of first N integers and return decimal value
Since n can be up to 10^9 we need to come up with solution that is better than O(n).
Here's some Python code that provides a fast solution; it uses the same ideas as in Abhinav Mathur's post. It requires Python >= 3.8, but it doesn't use anything particularly fancy from Python, and could easily be translated into another language. You'd need to write algorithms for modular exponentiation and modular inverse if they're not already available in the target language.
First, for testing purposes, let's define the slow and obvious version:
# Modulus that results are reduced by,
M = 10 ** 9 + 7
def slow_binary_concat(n):
"""
Concatenate binary representations of 1 through n (inclusive).
Reinterpret the resulting binary string as an integer.
"""
concatenation = "".join(format(k, "b") for k in range(n + 1))
return int(concatenation, 2) % M
Checking that we get the expected result:
>>> slow_binary_concat(4)
220
>>> slow_binary_concat(10)
462911642
Now we'll write a faster version. First, we split the range [1, n) into subintervals such that within each subinterval, all numbers have the same length in binary. For example, the range [1, 10) would be split into four subintervals: [1, 2), [2, 4), [4, 8) and [8, 10). Here's a function to do that splitting:
def split_by_bit_length(n):
"""
Split the numbers in [1, n) by bit-length.
Produces triples (a, b, 2**k). Each triple represents a subinterval
[a, b) of [1, n), with a < b, all of whose elements has bit-length k.
"""
a = 1
while n > a:
b = 2 * a
yield (a, min(n, b), b)
a = b
Example output:
>>> list(split_by_bit_length(10))
[(1, 2, 2), (2, 4, 4), (4, 8, 8), (8, 10, 16)]
Now for each subinterval, the value of the concatenation of all numbers in that subinterval is represented by a fairly simple mathematical sum, which can be computed in exact form. Here's a function to compute that sum modulo M:
def subinterval_concat(a, b, l):
"""
Concatenation of values in [a, b), all of which have the same bit-length k.
l is 2**k.
Equivalently, sum(i * l**(b - 1 - i)) for i in range(a, b)) modulo M.
"""
n = b - a
inv = pow(l - 1, -1, M)
q = (pow(l, n, M) - 1) * inv
return (a * q + (q - n) * inv) % M
I won't go into the evaluation of the sum here: it's a bit off-topic for this site, and it's hard to express without a good way to render formulas. If you want the details, that's a topic for https://math.stackexchange.com, or a page of fairly simple algebra.
Finally, we want to put all the intervals together. Here's a function to do that.
def fast_binary_concat(n):
"""
Fast version of slow_binary_concat.
"""
acc = 0
for a, b, l in split_by_bit_length(n + 1):
acc = (acc * pow(l, b - a, M) + subinterval_concat(a, b, l)) % M
return acc
A comparison with the slow version shows that we get the same results:
>>> fast_binary_concat(4)
220
>>> fast_binary_concat(10)
462911642
But the fast version can easily be evaluated for much larger inputs, where using the slow version would be infeasible:
>>> fast_binary_concat(10**9)
827129560
>>> fast_binary_concat(10**18)
945204784
You just have to note a simple pattern. Taking up your example for n=4, let's gradually build the solution starting from n=1.
1 -> 1 #1
2 -> 2^2(1) + 2 #6
3 -> 2^2[2^2(1)+2] + 3 #27
4 -> 2^3{2^2[2^2(1)+2]+3} + 4 #220
If you expand the coefficients of each term for n=4, you'll get the coefficients as:
1 -> (2^3)*(2^2)*(2^2)
2 -> (2^3)*(2^2)
3 -> (2^3)
4 -> (2^0)
Let the N be total number of bits in the string representation of our required number, and D(x) be the number of bits in x. The coefficients can then be written as
1 -> 2^(N-D(1))
2 -> 2^(N-D(1)-D(2))
3 -> 2^(N-D(1)-D(2)-D(3))
... and so on
Since the value of D(x) will be the same for all x between range (2^t, 2^(t+1)-1) for some given t, you can break the problem into such ranges and solve for each range using mathematics (not iteration). Since the number of such ranges will be log2(Given N), this should work in the given time limit.
As an example, the various ranges become:
1. 1 (D(x) = 1)
2. 2-3 (D(x) = 2)
3. 4-7 (D(x) = 3)
4. 8-15 (D(x) = 4)

How to convert a bitstream to a base20 number?

Given is a bitstream (continuous string of bits too long to be processed at once) and the result should be a matching stream of base20 numbers.
The process is simple for a small number of bits:
Assuming most significant bit right:
110010011 = decimal 403 (1 * 1 + 1 * 2 + 1 * 16 + 1 * 128 + 1 * 256)
403 / 20 = 20 R 3
20 / 20 = 1 R 0
1 / 20 = 0 R 1
Result is [3, 0, 1] = 3 * 1 + 0 * 20 + 1 * 400
But what if the bits are too much to be converted to a decimal number in one step?
My approach was doing both processes in a loop: Convert the bits to decimal and converting the decimal down to base20 numbers. This process requires the multipliers (position values) to be lowered while walking through the bits, because otherwise, they'll quickly increase too much to be calculated probably. The 64th bit would have been multiplied by 2^64 and so on.
note: I understood the question that a bitstream is arriving of unknown length and during an unknown duration and a live conversion from base 2 to base 20 should be made.
I do not believe this can be done in a single go. The problem is that base 20 and base 2 have no common ground and the rules of modular arithmetic do not allow to solve the problem cleanly.
(a+b) mod n = ( (a mod n) + (b mod n) ) mod n
(a*b) mod n = ( (a mod n) * (b mod n) ) mod n
(a^m) mod n = ( (a mod n)^m ) mod n
Now if you have a number A written in base p and q (p < q) as
A = Sum[a[i] p^i, i=0->n] = Sum[b[i] q^i, i=0->n]
Then we know that b[0] = A mod q. However, we do not know A and hence, the above tells us that
b[0] = A mod q = Sum[a[i] p^i, i=0->n] mod q
= Sum[ (a[i] p^i) mod q, i=0->n] mod q
= Sum[ ( (a[i] mod q) (p^i mod q) ) mod q, i=0->n] mod q
This implies that:
If you want to know the lowest digit b0 of a number in base q, you need to have the knowledge of the full number.
This can only be simplified if q = pm as
b[0] = A mod q = Sum[a[i] p^i, i=0->n] mod q
= Sum[ (a[i] p^i) mod q, i=0->n] mod q
= Sum[ a[i] p^i, i=0->m-1]
So in short, since q = 20 and p = 2. I have to say, no, it can not be done in a single pass. Furthermore, remind yourself that I only spoke about the first digit in base q and not yet the ith digit.
As an example, imagine a bit stream of 1000 times 0 followed by a single 1. This resembles the number 21000. The first digit is easy, but to get any other digit ... you are essentially in a rather tough spot.

Sum of powers in Prolog

I'm trying to implement a method to work as follows foo(5) = 5^4 + 4^3 + 3^2 + 2^1 + 1^0 = 701 using recursion. I've been trying to follow the logic but I keep getting errors. can someone guide me?
(define (foo n) ; size-n problem
( cond ( (= (- n 1) 0 ) ; stopping condition
0 ); return value
(else (+ ( expt n (- n 1) ) ( foo (- n 1) ) ) ))) ; size-m problems
If you tagged the question correctly, you want to answer this in Prolog, but your code fragment suggests you use lisp (or a language that I don't know).
In Prolog you write predictes. For your problem, there are two cases:
The case where N is less than or equal to zero, which is zero:
foo(N,0) :-
N =< 0,
!.
The inductive case when N is greater than 0. In that case we calculate foo for N-1 and add up N^(N-1):
foo(N,S) :-
N1 is N-1,
foo(N1,T),
S is T+N^N1.
You can simply write program containing the two cases:
foo(N,0) :-
N =< 0,
!.
foo(N,S) :-
N1 is N-1,
foo(N1,T),
S is T+N^N1.
And test it as follows:
?- foo(-1,S).
S = 0.
?- foo(0,S).
S = 0.
?- foo(1,S).
S = 1.
?- foo(2,S).
S = 3.
?- foo(3,S).
S = 12.
?- foo(5,S).
S = 701.
You can akso make th is predicate more safer from looping by adding a check for the inductive case:
foo(N,0) :-
N =< 0,
!.
foo(N,S) :-
N > 0,
N1 is N-1,
foo(N1,T),
S is T+N^N1.
Or you can further boost the predicate's performance using an accumulator:
foo(N,S) :-
foo(N,0,S).
foo(N,S,T) :-
N > 0,
!,
N1 is N-1,
Q is S+N^N1,
foo(N1,Q,T).
foo(N,S,S) :-
N =< 0.
This version also checks first whether N > 0 before N =< 0 because it is a much more likely scenario: after one N =< 0 we stop recursion whereas the N > 0 will be called N-1 times. Using an accumulator enables a optimization technique called tail recursion.

Unclassified statement at (1) in a mathematical expression

My first Fortran lesson is to plot the probability density function of the radial Sturmian functions. In case you are interested, the radial Sturmian functions are used to graph the momentum space eigenfunctions for the hydrogen atom.
In order to produce these radial functions, one needs to first produce some polynomials called the Gegenbauer polynomials, denoted
Cba(x),
where a and b should be stacked atop each other. One needs these polynomials because the Sturmians (let's call them R_n,l) are defined like so,
R_n,l(p) = N pl⁄(p2 + k2)l+2 Cn - l - 1l + 1(p2 - k2⁄p2 + k2),
where N is a normalisation constant, p is the momentum, n is the principle quantum number, l is the angular momentum and k is a constant. The normalisation constant is there so that when I come to square this function, it will produce a probability distribution for the momentum of the electron in a hydrogen atom.
Gegenbauer polynomials are generated using the following recurrence relation:
Cnl(x) = 1⁄n[2(l + n - 1) x Cn - 1l(x) - (2l + n - 2)Cn - 2l(x)],
with C0l(x) = 1 and C1l(x) = 2lx, as you may have noticed, l is fixed but n is not. At the start of my program, I will specify both l and n and work out the Gegenbauer polynomial I need for the radial function I wish to plot.
The problems I am having with my code at the moment are all in my subroutine for working out the value of the Gegenbauer polynomial Cn-l-1l+1(p2 - k2⁄p2 + k2) for incremental values of p between 0 and 3. I keep getting the error
Unclassified statement at (1)
but I cannot see what the issue is.
program Radial_Plot
implicit none
real, parameter :: pi = 4*atan(1.0)
integer, parameter :: top = 1000, l = 50, n = 100
real, dimension(1:top) :: x, y
real increment
real :: a=0.0, b = 2.5, k = 0.3
integer :: i
real, dimension(1:top) :: C
increment = (b-a)/(real(top)-1)
x(1) = 0.0
do i = 2, top
x(i) = x(i-1) + increment
end do
Call Gegenbauer(top, n, l, k, C)
y = x*C
! y is the function that I shall be plotting between values a and b.
end program Radial_Plot
Subroutine Gegenbauer(top1, n1, l1, k1, CSub)
! This subroutine is my attempt to calculate the Gegenbauer polynomials evaluated at a certain number of values between c and d.
implicit none
integer :: top1, i, j, n1, l1
real :: k1, increment1, c, d
real, dimension(1:top1) :: x1
real, dimension(1:n1 - l1, 1:top1) :: C1
real, dimension(1:n1 - l1) :: CSub
c = 0.0
d = 3.0
k1 = 0.3
n1 = 50
l1 = 25
top1 = 1000
increment1 = (d - c)/(real(top1) - 1)
x1(1) = 0.0
do i = 2, top1
x1(i) = x1(i-1) + increment1
end do
do j = 1, top1
C1(1,j) = 1
C1(2,j) = 2(l1 + 1)(x1(i)^2 - k1^2)/(x1(i)^2 + k1^2)
! All the errors occurring here are all due to, and I quote, 'Unclassifiable statement at (1)', I can't see what the heck I have done wrong.
do i = 3, n1 - l1
C1(i,j) = 2(((l1 + 1)/n1) + 1)(x1(i)^2 - k1^2)/(x1(i)^2 + k1^2)C1(i,j-1) - ((2(l1+1)/n1) + 1)C1(i,j-2)
end do
CSub(j) = Cn(n1 - l1,j)^2
end do
return
end Subroutine Gegenbauer
As francesalus correctly pointed out, the problem is because you use ^ instead of ** for exponentiation. Additionally, you do not put * between the terms you are multiplying.
C1(1,j) = 1
C1(2,j) = 2*(l1 + 1)*(x1(i)**2 - k1**2)/(x1(i)**2 + k1**2)
do i = 3, n1 - l1
C1(i,j) = 2 * (((l1 + 1)/n1) + 1) * (x1(i)**2 - k1**2) / &
(x1(i)**2 + k1**2)*C1(i,j-1) - ((2(l1+1)/n1) + 1) * &
C1(i,j-2)
end do
CSub(j) = Cn(n1 - l1,j)**2
Since you are beginning I have some advice. Learn to put all subroutines and functions to modules (unless they are internal). There is no reason for the return statement at the and of the subroutine, similarly as a stop statement isn't necessary at the and of the program.

Testing divisibility of Ints by 11

I'm struggling with this code right now. I want to determine whether an integer is divsible by 11. From what I have read, an integer is divisible to 11 when the sum (one time +, one time -) of its digits is divisible by 11.
For example: 56518 is divisible by 11, because 8-1+5-6+5 = 11, and 11 is divisible by 11.
How can i write this down in Haskell? Thanks in advance.
A number x is divisible by y if it's remainder when divided by y is 0. So you can just do
divisibleBy11 x = x `rem` 11 == 0
ifan I'm sure you know that in real life you would use mod or rem for this simple example, but the algorithm you are asking about is interesting. Here's a fun way to do it that emphasizes the functional nature of Haskell:
digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)
divisible11 = (== 0) . head . dropWhile (>= 11) . iterate (reduce11 . digits)
where
reduce11 [] = 0
reduce11 (d:ds) = foldl combine d $ zip (cycle [(-), (+)]) ds
combine d (op, d') = d `op` d'
Surely, div and mod are faster, but why not? I assume the problem is converting a number to a list of digits:
toDigits = map (read . (:[])) . show
56518 is converted to a String "56518", and each symbol in the string (every digit) is converted to a string itself with map (:[]), at this point we have ["5","6","5","1","8"], and we read every single-digit string as an integer value: [5,6,5,1,8]. Done.
Now we can calculate the sum of digits this way:
sumDigits x = sum (zipWith (*) (cycle [1,-1]) (reverse (toDigits x)))
cycle [1,-1] makes an infinite list [1, -1, 1, -1, ...], which we pair with the reversed list of digits (toDigit x), and multiply elements of every pair. So we have [8, -1, 5, -6, 5] and its sum.
Now we can do it recursively:
isDivisible x
| x == 11 || x == 0 = True
| x < 11 = False
| x > 11 = isDivisible (sumDigits x)
How about...
mod11 n | n < 0 = 11 - mod11 (-n)
| n < 11 = n
| otherwise = mod11 $ (n `mod` 10) - (n `div` 10)

Resources