This is what I tried to convert Octal number to binary.
What I wanted to do was to find the remainder of the given octal number when divided by 10 to get each digit and convert that digit to 3 bit binary. But this code is not producing any output. Please help on this.
Thanks in advance.
convert_bin(0, '0').
convert_bin(1, '1').
convert_bin(N, B) :-
N > 1,
X is N mod 2,
Y is N // 2,
convert_bin(Y, B1),
atom_concat(B1, X, B).
convert_oct(N, O) :-
X is N mod 10,
convert_bin(X, B),
Y is N // 10,
convert_oct(Y, O1),
atom_concat(O1, B, O).
The encoded number should better be a list of digits—not an atom!
Using clpfd and n_base_digits/3 we can write the following sample queries:
?- use_module(library(clpfd)).
true.
?- n_base_digits(27, 2, Binary).
Binary = [1,1,0,1,1].
?- n_base_digits(N, 2, [1,1,0,0,1,0,0,1]).
N = 201
; false.
?- n_base_digits(N, 2, [1,1,0,0,1,0,0,1]),
n_base_digits(N, 8, Octal).
N = 201, Octal = [3,1,1]
; false.
Related
I need to write the function to check if the number binary representation doesn't contain duplications. For example, the function must return true if N equals to 42, because bin(42) equals to 101010, but if N equals to 45 the function must return false, because of binary representation of 45 which equals to 101101 and which contains duplicates 11.
This allows only bits that alternate between 0 and 1, plus possibly leading zeros.
One way to check this is to look at (N << 2) | N. If N is of the correct form, then this is equal to N << 2, except for bit 0 or 1. We can compensate for that as follows:
unsigned N2 = N << 2;
return (N | N2) <= (N2 | 2);
Is there an equation I can use for arbitrary M and N?
Example, N=3 and M=2:
3 bits allow for 8 different combinations, but only 2 of them do not contain more than 2 same symbols in a row
000 - Fails
001 - Fails
010 - OK
011 - Fails
100 - Fails
101 - OK
110 - Fails
111 - Fails
One way to frame the problem is as follows: we would like to count binary words of length n without runs of length m or larger. Let g(n, m) denote the number of such words. In the example, n = 3 and m = 2.
If n < m, every binary word works, and we get g(n, m) = 2^n words in total.
When n >= m, we can choose to start with 1, 2, ... m-1 repeated values,
followed by g(n-1, m), g(n-2, m), ... g(n-m+1, m) choices respectively. Combined, we get the following recursion (in Python):
from functools import lru_cache
#lru_cache(None) # memoization
def g(n, m):
if n < m:
return 2 ** n
else:
return sum(g(n-j, m) for j in range(1, m))
To test for correctness, we can compute the number of such binary sequences directly:
from itertools import product, groupby
def brute_force(n, k):
# generate all binary sequences of length n
products = product([0,1], repeat=n)
count = 0
for prod in products:
has_run = False
# group consecutive digits
for _, gp in groupby(prod):
gp_size = sum(1 for _ in gp)
if gp_size >= k:
# there are k or more consecutive digits in a row
has_run = True
break
if not has_run:
count += 1
return count
assert 2 == g(3, 2) == brute_force(3, 2)
assert 927936 == g(20, 7) == brute_force(20, 7)
I was trying to implement various forms of queries on Hailstone Sequence.
Hailstone sequences are sequences of positive integers with the following properties:
1 is considered the terminating value for a sequence.
For any even positive integer i, the value that comes after i in the sequence is i/2.
For any odd positive integer j > 1, the value that comes after j in the sequence is 3j+1
Queries can be
hailSequence(Seed,Sequence): where the Sequence is the hailstone sequence generated from the given Seed.
hailStone(M,N): where N is the number that follows M in a hailstone sequence. E.g. if M is 5 then N should be 16, if M is 20 then N should be 10, etc.
hailStorm(Seed,Depth,HailTree): where HailTree is the tree of values that could preceed Seed in a sequence of the specified depth.
Example:
| ?- hailStorm(1,4,H).
H = hs(1,hs(2,hs(4,hs(8)))) ?
yes
| ?- hailStorm(5,3,H).
H = hs(5,hs(10,hs(3),hs(20))) ?
yes
Pictorial Representation
Now I've implemented the first two predicates:
hailSequence(1,[1]) :- !.
hailSequence(N,[N|S]) :- 0 is N mod 2, N1 is round(N / 2), hailSequence(N1,S).
hailSequence(N,[N|S]) :- 1 is N mod 2, N1 is (3 * N) + 1, hailSequence(N1, S).
hailStone(X,Y) :- nonvar(X), 0 is X mod 2, Y is round(X / 2).
hailStone(X,Y) :- nonvar(X), 1 is X mod 2, Y is (3 * X) + 1.
hailStone(X,Y) :- nonvar(Y), 1 is Y mod 3, T is round( (Y - 1) / 3), 1 is T mod 2, X is T.
For the hailStorm/2 predicate, I've written the following code, but it is not working as expected:
make_hs1(S,hs(S)).
make_hs2(S,R,hs(S,make_hs1(R,_))).
make_hs3(S,L,R,hs(S,make_hs1(L,_),make_hs1(R,_))).
hailStorm(S,1,hs(S)) :- !.
hailStorm(S,D,H) :- nonvar(S), nonvar(D), 4 is S mod 6, S=\= 4, make_hs3(S,hailStorm(round((S-1)/3),D-1,_X),hailStorm(2*S,D-1,_Y),H).
hailStorm(S,D,H) :- nonvar(S), nonvar(D), make_hs2(S,hailStorm(2*S,D-1,_X),H).
Output:
| ?- hailStorm(5,2,H).
H = hs(5,make_hs1(hailStorm(2*5,2-1,_),_))
yes
which is not the desired output,i.e.,
H = hs(5,hs(10)) ?
There are several issues expressed in the problem statement:
In Prolog, there are predicates and terms but not functions. Thinking of them as functions leads one to believe you can write terms such as, foo(bar(3), X*2)) and expect that Prolog will call bar(3) and evaluate X*2 and then pass these results as the two arguments to foo. But what Prolog does is pass these just as terms as you see them (actually, X*2 internally is the term, *(X,2)). And if bar(3) were called, it doesn't return a value, but rather either succeeds or fails.
is/2 is not a variable assignment operator, but rather an arithmetic expression evaluator. It evaluates the expression in the second argument and unifies it with the variable or atom on the left. It succeeds if it can unify and fails otherwise.
Although expressions such as 0 is N mod 2, N1 is round(N / 2) will work, you can take more advantage of integer arithmetic in Prolog and write it more appropriately as, 0 =:= N mod 2, N1 is N // 2 where =:= is the arithmetic comparison operator. You can also use bit operations: N /\ 1 =:= 0, N1 is N // 2.
You haven't defined a consistent definition for what a hail storm tree looks like. For example, sometimes your hs term has one argument, and sometimes it has three. This will lead to unification failures if you don't explicitly sort it out in your predicate hailStorm.
So your hailSequence is otherwise correct, but you don't need the cut. I would refactor it a little as:
hail_sequence(1, [1]).
hail_sequence(Seed, [Seed|Seq]) :-
Seed > 1,
Seed /\ 1 =:= 0,
S is Seed // 2,
hail_sequence(S, Seq).
hail_sequence(Seed, [Seed|Seq]) :-
Seed > 1,
Seed /\ 1 =:= 1,
S is Seed * 3 + 1,
hail_sequence(S, Seq).
Or more compactly, using a Prolog if-else pattern:
hail_sequence(1, [1]).
hail_sequence(Seed, [Seed|Seq]) :-
Seed > 1,
( Seed /\ 1 =:= 0
-> S is Seed // 2
; S is Seed * 3 + 1
),
hail_sequence(S, Seq).
Your description for hailStone doesn't say it needs to be "bidirectional" but your implementation implies that's what you wanted. As such, it appears incomplete since it's missing the case:
hailStone(X, Y) :- nonvar(Y), Y is X * 2.
I would refactor this using a little CLPFD since it will give the "bidirectionality" without having to check var and nonvar. I'm also going to distinguish hail_stone1 and hail_stone2 for reasons you'll see later. These represent the two ways in which a hail stone can be generated.
hail_stone(S, P) :-
hail_stone1(S, P) ; hail_stone2(S, P).
hail_stone1(S, P) :-
S #> 1,
0 #= S rem 2,
P #= S // 2.
hail_stone2(S, P) :-
S #> 1,
1 #= S rem 2,
P #= S * 3 + 1.
Note that S must be constrained to be > 1 since there is no hail stone after 1. If you want these using var and nonvar, I'll leave that as an exercise to convert back. :)
Now to the sequence. First, I would make a clean definition of what a tree looks like. Since it's a binary tree, the common representation would be:
hs(N, Left, Right)
Where Left and Right are branchs (sub-trees), which could have the value nul, n, nil or whatever other atom you wish to represent an empty tree. Now we have a consistent, 3-argument term to represent the tree.
Then the predicate can be more easily defined to yield a hail storm:
hail_storm(S, 1, hs(S, nil, nil)). % Depth of 1
hail_storm(S, N, hs(S, HSL, HSR)) :-
N > 1,
N1 is N - 1,
% Left branch will be the first hail stone sequence method
( hail_stone1(S1, S) % there may not be a sequence match
-> hail_storm(S1, N1, HSL)
; HSL = nil
),
% Right branch will be the second hail stone sequence method
( hail_stone2(S2, S) % there may not be a sequence match
-> hail_storm(S2, N1, HSR)
; HSR = nil
).
From which we get, for example:
| ?- hail_storm(10, 4, Storm).
Storm = hs(10,hs(20,hs(40,hs(80,nil,nil),hs(13,nil,nil)),nil),hs(3,hs(6,hs(12,nil,nil),nil),nil)) ? ;
(1 ms) no
If you want to use the less symmetrical and, arguably, less canonical definition of binary tree:
hs(N) % leaf node
hs(N, S) % one sub tree
hs(N, L, R) % two sub trees
Then the hail_storm/3 predicate becomes slightly more complex but manageable:
hail_storm(S, 1, hs(S)).
hail_storm(S, N, HS) :-
N > 1,
N1 is N - 1,
( hail_stone1(S1, S)
-> hail_storm(S1, N1, HSL),
( hail_stone2(S2, S)
-> hail_storm(S2, N1, HSR),
HS = hs(S, HSL, HSR)
; HS = hs(S, HSL)
)
; ( hail_stone2(S2, S)
-> hail_storm(S2, N1, HSR),
HS = hs(S, HSR)
; HS = hs(S)
)
).
From which we get:
| ?- hail_storm1(10, 4, Storm).
Storm = hs(10,hs(20,hs(40,hs(80),hs(13))),hs(3,hs(6,hs(12)))) ? ;
no
I'm new to Haskell, started learning a couple of days ago and I have a question on a function I'm trying to make.
I want to make a function that verifies if x is a factor of n (ex: 375 has these factors: 1, 3, 5, 15, 25, 75, 125 and 375), then removes the 1 and then the number itself and finally verifies if the number of odd numbers in that list is equal to the number of even numbers!
I thought of making a functions like so to calculate the first part:
factor n = [x | x <- [1..n], n `mod`x == 0]
But if I put this on the prompt it will say Not in scope 'n'. The idea was to input a number like 375 so it would calculate the list. What I'm I doing wrong? I've seen functions being put in the prompt like this, in books.
Then to take the elements I spoke of I was thinking of doing tail and then init to the list. You think it's a good idea?
And finally I thought of making an if statement to verify the last part. For example, in Java, we'd make something like:
(x % 2 == 0)? even++ : odd++; // (I'm a beginner to Java as well)
and then if even = odd then it would say that all conditions were verified (we had a quantity of even numbers equal to the odd numbers)
But in Haskell, as variables are immutable, how would I do the something++ thing?
Thanks for any help you can give :)
This small function does everything that you are trying to achieve:
f n = length evenFactors == length oddFactors
where evenFactors = [x | x <- [2, 4..(n-1)], n `mod` x == 0]
oddFactors = [x | x <- [3, 5..(n-1)], n `mod` x == 0]
If the "command line" is ghci, then you need to
let factor n = [x | x <- [2..(n-1)], n `mod` x == 0]
In this particular case you don't need to range [1..n] only to drop 1 and n - range from 2 to (n-1) instead.
The you can simply use partition to split the list of divisors using a boolean predicate:
import Data.List
partition odd $ factor 10
In order to learn how to write a function like partition, study recursion.
For example:
partition p = foldr f ([],[]) where
f x ~(ys,ns) | p x = (x:ys,ns)
f x ~(ys,ns) = (ys, x:ns)
(Here we need to pattern-match the tuples lazily using "~", to ensure the pattern is not evaluated before the tuple on the right is constructed).
Simple counting can be achieved even simpler:
let y = factor 375
(length $ filter odd y) == (length y - (length $ filter odd y))
Create a file source.hs, then from ghci command line call :l source to load the functions defined in source.hs.
To solve your problem this may be a solution following your steps:
-- computers the factors of n, gets the tail (strips 1)
-- the filter functions removes n from the list
factor n = filter (/= n) (tail [x | x <- [1..n], n `mod` x == 0])
-- checks if the number of odd and even factors is equal
oe n = let factors = factor n in
length (filter odd factors) == length (filter even factors)
Calling oe 10 returns True, oe 15 returns False
(x % 2 == 0)? even++ : odd++;
We have at Data.List a partition :: (a -> Bool) -> [a] -> ([a], [a]) function
So we can divide odds like
> let (odds,evens) = partition odd [1..]
> take 10 odds
[1,3,5,7,9,11,13,15,17,19]
> take 10 evens
[2,4,6,8,10,12,14,16,18,20]
Here is a minimal fix for your factor attempt using comprehensions:
factor nn = [x | n <- [1..nn], x <- [1..n], n `mod`x == 0]
Here is my predicate, which should check if the Nth number of Fibonacci is NthFib or not.
I am getting arithmetic is not function error.
K - current iteration
N - Nth number
Tmp - previous Fibonacci number
Ans - current Fibonacci number
Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, etc. (sum of two previous = current)
fib(N, NthFib) :-
fib(1, N, 1, 0, NthFib).
fib(K, N, Ans, Tmp, NthFib) :-
% true if Ans is NthFib, false otherwise
( K > N -> Ans is NthFib
; K =< N -> fib( K + 1, N, Ans + Tmp, Ans, NthFib)
).
First, re-write your original code as
fib(N, NthFib) :- fib(1, N, 1, 0, NthFib).
fib(K, N, Ans, Tmp, NthFib) :-
K > N -> Ans = NthFib; % use = instead of is here
K =< N -> fib((K+1), N, (Ans+Tmp), Ans, NthFib).
Now,
?- fib(7,X).
X = 1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0))+ (1+0+1+ (1+0)+ (1+0+1))+
(1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0)))
Yes
?- fib(7,X), Z is X.
X = 1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0))+ (1+0+1+ (1+0)+ (1+0+1))+
(1+0+1+ (1+0)+ (1+0+1)+ (1+0+1+ (1+0)))
Z = 21
See, in Prolog data is symbolic, and using is forces the arithmetic expression into an arithmetic value (evaluates the expression under assumption that it is a meaningful arithmetic expression).
To check whether 20 is 7-th Fibonacci number, we can use arithmetic comparison operator which evaluates its arguments,
?- fib(7,X), X =:= 20.
No
Which means that your code just needs to be rewritten as
fib(N, NthFib) :- fib(1, N, 1, 0, NthFib).
fib(K, N, Ans, Tmp, NthFib) :-
K > N -> NthFib is Ans ; % exchange the order of operands
K =< N -> fib((K+1), N, (Ans+Tmp), Ans, NthFib).
Now it works as you intended:
?- fib(7,21).
Yes
?- fib(7,20).
No
But it doesn't work efficiently, carrying all those long expressions around as symbolic data. We only need the numbers really, so just as you were shown in other answers, is is used to achieve that. Every symbolic sub-expression that you have, take it out of its enclosing expression, and name it, using is instead of =.
BTW 21 really is an 8-th member of the sequence. Correct your code.
If K is unified with 1, K + 1 is unified with 1 + 1, not 2.
I have rewrote an algorithm, it is more simple and efficient now:
fib(0, 0).
fib(1, 1).
fib(N, F) :-
N > 0,
X is N - 2,
Y is N - 1,
fib(X, A),
fib(Y, B),
F is A + B.