I wrote a Prolog program to find all solutions to any '8 out of 10 cats does countdown' number sequence. I am happy with the result. However, the solutions are not unique. I tried distincts() and reduced() from the "solution sequences" library. They did not produce unique solutions.
The problem is simple. you have a given list of six numbers [n1,n2,n3,n4,n5,n6] and a target number (R). Calculate R from any arbitrary combination of n1 to n6 using only +,-,*,/. You do not have to use all numbers but you can only use each number once. If two solutions are identical, only one must be generated and the other discarded.
Sometimes there are equivalent results with different arrangement. Such as:
(100+3)*6*75/50+25
(100+3)*75*6/50+25
Does anyone has any suggestions to eliminate such redundancy?
Each solution is a nested operators and integers. For example +(2,*(4,-(10,5))). This solution is an unbalanced binary tree with Arithmetic Operator for root and sibling nodes and numbers for leaf nodes. In order to have unique solutions, no two trees should be equivalent.
The Code:
:- use_module(library(lists)).
:- use_module(library(solution_sequences)).
solve(L,R,OP) :-
findnsols(10,OP,solve_(L,R,OP),S),
print_solutions(S).
solve_(L,R,OP) :-
distinct(find_op(L,OP)),
R =:= OP.
find_op(L,OP) :-
select(N1,L,Ln),
select(N2,Ln,[]),
N1 > N2,
member(OP,[+(N1,N2), -(N1,N2), *(N1,N2), /(N1,N2), N1, N2]).
find_op(L,OP) :-
select(N,L,Ln),
find_op(Ln,OP_),
OP_ > N,
member(OP,[+(OP_,N), -(OP_,N), *(OP_,N), /(OP_,N), OP_]).
print_solutions([]).
print_solutions([A|B]) :-
format('~w~n',A),
print_solutions(B).
Test:
solve([25,50,75,100,6,3],952,X)
Result
(100+3)*6*75/50+25 <- s1
((100+6)*3*75-50)/25 <- s2
(100+3)*75*6/50+25 <- s1
((100+6)*75*3-50)/25 <- s2
(100+3)*75/50*6+25 <- s1
true.
This code uses select/3 from the "lists" library.
UPDATE: Generate solutions useing DCG
The following is an attempt to generate solutions using DCG. I was able to generate a more exhaustive solution set than in previous code posted. In a way, using DCG resulted in a more correct and elegant code. However, it is much more difficult to 'guess' what the code is doing.
The issue of redundant solutions still persist.
:- use_module(library(lists)).
:- use_module(library(solution_sequences)).
s(L) --> [L].
s(+(L,Ls)) --> [L],s(Ls).
s(*(L,Ls)) --> [L],s(Ls), {L =\= 1, Ls =\= 1, Ls =\= 0}.
s(-(L,Ls)) --> [L],s(Ls), {L =\= Ls, Ls =\= 0}.
s(/(L,Ls)) --> [L],s(Ls), {Ls =\= 1, Ls =\= 0}.
s(-(Ls,L)) --> [L],s(Ls), {L =\= Ls}.
s(/(Ls,L)) --> [L],s(Ls), {L =\= 1, Ls =\=0}.
solution_list([N,H|[]],S) :-
phrase(s(S),[N,H]).
solution_list([N,H|T],S) :-
phrase(s(S),[N,H|T]);
solution_list([H|T],S).
solve(L,R,S) :-
permutation(L,X),
solution_list(X,S),
R =:= S.
Does anyone has any suggestions to eliminate such redundancy?
I suggest to define a sorting weight on each node (inner or leaf). The number resulting from reducing the child node could be used, although ties will appear. These can be broken by additionally looking at topmost operations, sorting * before + for example. Actually one would like to have a sorting operation for which "tie" means "exactly the same subtree of arithmetic operations".
Since the OP is only seeking hints to help solve the problem.
Use DCG as a generator. (SWI-Prolog) (Prolog DCG Primer)
a. For a more refined version of using DCGs as a generator look for examples that use length/2. When you understand why you might see a beam of light shining down on you for a few moments (The light beam is a video gaming thing).
Use a constraint solver (SWI-Prolog) (CLP(FD) and CLP(ℤ): Prolog Integer Arithmetic) (Understanding CLP(FD) Prolog code of N-queens problem)
Since your solutions are constrained to the 6 numbers and the operators are always binary operators (+,-,*,/) then it is possible to enumerate the unique binary trees. If you know about OEIS then you can find related links that can help you solve this problem, but you need to give OEIS a sequence. To get a sequence for use with OEIS draw the trees for N from 2 to 5 and then enter that sequence into OEIS and see what you get. e.g.
N is the number of leaf (*) nodes.
N=2 ( 1 way to draw the tree )
-
/ \
* *
N=3 ( 2 ways to draw the tree )
- -
/ \ / \
- * * -
/ \ / \
* * * *
So the sequence starts with 1,2 ...
Hint - This page (link died) shows the images of the trees to see if you have done it correctly. In the description I use N to count the number of leaves (*), but on this page they use N to count the number of internal nodes (-). If we call my N N1 and the page N N2, then the relation is N2 = N1 - 1
This might be a Hamiltonian Cycle (Wolfram World) (Hamiltonianicity of the Tower of Hanoi Problem) Remember that there is a relation between Binary Trees and the Tower of Hanoi, but in your case there are added constraints. I don't know if the constraints eliminate a solution as a Hamiltonian Cycle.
Also don't think of building the final answer from a combination of any number and operator, but instead build subsets of operators and numbers, and then use those subsets to build the answer. You constrain at the start, not at the end.
Or put another way, don't think combinations at the start, but permutations of combinations (not sure if that is the correct pattern, but in the ball park) and then using that build the tree.
I am trying to prove that the following language is not regular using the pumping lemma.
L = {ak b3l al | k ≥ 1 , l ≥ 0}
I have decided to choose w = a b3p ap, then |w| = 4p+1 ≥ p
Any tips?
Thank you!
I am not sure about the exact formulation of the pumping lemma that you are using. At any rate, this is a rather tricky case, because standard formulations like in wikipedia only let you pump somewhere in a prefix of fixed length. But your initial block of a allows pumping anywhere and can be arbitrarily long. Thus you have to use some additional property. I suggest two:
Regular languages are closed under reversal. Thus you may as well look at $L^R = {a^l b^{3l} a^k}$. Now any pumping in the initial block of a will lead out of the language.
Regular languages are closed under intersection. If you take the intersection with a b+ a+ you end up with ${a b^{3l} a^k}$, and now pumping in the b block will take you out of the language.
L = {a^3^k | k element N} is subset of {a,b}*
I have to prove that the language L is not regular, but I don't know what the subset means for the proof.
{a^3^k | k element N} should be regular because I can draw a DFA and I also can draw a DFA of {a, b}.
It's not regular. In fact a very good rule of thumb to tell at a glance is if the language is trying to count characters in a non-repeatable fashion.
You can't count with a single regular expression a sequence like 1, 3, 9, 27 while making sure all the other counts fail, you need something repeatable like \d{5} in normal regex notation.
I'll leave the proof up to you since this is obviously homework, just clarifying the misconception that this is regular because you can draw the first two elements. Sure you can, but you can't draw the generic term in a general way!
I have a little confusion in checking whether the given language is regular or not using pumping lemma.
Suppose we have to check whether:
L. The language accepting even number of 0's in regular or not?
We know that it is regular because we can construct a DFA for L. But I want to prove this with pumping lemma.
Now suppose, I take a String w= "0000":
Now will divide the string as x = 0, y = 0, and z = 00. Now on applying pumping lemma for i = 2, I will get the string "00000", which is not present in my language so by pumping lemma its prove that the language is not regular. But it is accepted by DFA ?
Any help will be greatly appreciated
Thank you
You are not completely clear about pumping lemma.
What pumping lemma say:
Formal definition: Pumping lemma for regular languages
Let L be a regular language. Then there exists an integer p ≥ 1 depending only on L such that every string w in L of length at least p (p is called the "pumping length") can be written as w = xyz (i.e., w can be divided into three substrings), satisfying the following conditions:
|y| ≥ 1
|xy| ≤ p
for all i ≥ 0, xyiz ∈ L
But what this statement says is that:
If a language is really a regular language then there must be some way to generate(pump) new strings from all sufficiently large strings.
Sufficiently large string means, a string in language that is of the length ≥ P.
So it may not be possible to generate new string from small strings even if language is Regular Language
Some way means, if language is really a regular and our choice of w is correct. Then there should be at lest one way to break w in three parts xyz such that by repeating(pumping) y for any number of times we can generate new strings in the language.
correct choice of w means: w in language and sufficiently large ≥ P
note: in second point, there may be a chance that even if you breaks w correctly into xyz according to formal definition still some new generated strings are not in language. As you did.
And in this situation you are to retry with some other possible choice of y.
In you chosen string w = "0000" you can break w such that y = 00. And with this choice of y you would always find a new generated string in in Language that is "even number of zeros"
One mistake you are doing in your proof that you are doing for a specific string 0000. You should proof for all w ≥ P. So still your proof is incomplete
Read my this answer IN CONTEXT OF PUMPING LEMMA FOR REGULAR LANGUAGES
In that answer, I have explained that breaking w into xyz and pumping y means finding looping part and repeating looping part to generate new strings in language.
When we proof that some language is regular; then actually we don't know where is the looping part so we try with all possible choices that satisfies pumping lemma's rule 1,2 & 3.
And Pumping lemma says that if language is regular and infinite them there must be a loop in the DFA and every sufficiently large string in language passes through looping part (according to pigeonhole principle) of DFA (and hence y can't be null. That's rule-1 in above formal definition).
Think, loop can be at initial position or at end and so x and z can be null strings.
But actually we don't know where loop falls in DFA so we try with all possible ways.
To proof a language is regular: You are to proof that for all sufficiently long strings(w) in language there is at-least one way(y) to generate new strings in the language by repeating looping part any number (i) of times.
To proof a language is not regular:You are to find at least one sufficiently long strings (w) in language such that there no choice for any way 'y' so that its possible to generate new strings with all possible repetition (i).
To proof using Pumping Lemma:
+-------------------------+--------------------------+----------------+--------------+
| | Sufficient large W in L | y | i >=0 |
+-------------------------+--------------------------+----------------+--------------+
| language is regular | For all W (all W can use | At-least one | For all i>=0 |
| | to generate new W' in L) | | |
+-------------------------+--------------------------+----------------+--------------+
| language is NOT regular | Find Any W (at-least 1 | With all (Show | At-least one |
| | W that can't generates | no possible Y | i |
| | new W' in L | exists) | |
+-------------------------+--------------------------+----------------+--------------+
CAUTION:: The Rule always not works to proof 'Weather a Language is Regular?'
Pumping Lemma necessary but not sufficient condition for a language to be regular. A language possible that satisfies these conditions may still be non-regular.
Reference
To proof a language is regular you have some necessary and sufficient conditions for a language to be regular.
Although the accepted answer is complete in its own way, I had to add a few things. I have a very playful way to exploit the pumping lemma to be able to prove that a given language is not a Regular language.
Just to have a context to talk about, let me state the lemma:
Pumping Lemma for Regular Languages:
For any regular language L, there exists an integer k.
Such that for all x ∈ L with |x| ≥ k, there exists u, v, w ∈ Σ∗, such
that x = uvw, and
(1) |uv| ≤ k
(2) |v| ≥ 1
(3) for all i ≥ 0: u(v^i)w ∈ L
The k is called the Pumping lemma constant. Let me come straight to the point and show you how to go about proving a language L is not regular.
Now to start the game you need two players here. One is the Reader(R) and the other is the Adversary(A).
Input: A language L
The Goal of R: Somehow prove the language L is not regular by some contradiction.
The Goal of A: Somehow be prepared enough to face the arguments of R and do not let him/her create a contradiction.
Now let us start the argument.
A: The language L is not Irregular because none could show the contradiction using pumping lemma with a certain pumping constant k. (Each language is mapped to only one integer k)
R: Let me assume what you say. If language L is regular then it must satisfy the conditions of the pumping lemma. So, let me choose a suitable string x ∈ L (|x| >= k), such that it helps me create a contradiction later.
A: Challenged by the R, A tries its best to find at least one suitable partitioning u, v and w of the string x, such that
x = uvw and |uv| <= k and |v| > 0
R: With any possible partition given by A, wins the the argument if able to show an integer i >= 0 such that
u(v^i)w ∉ L
Because now the R has shown that the Language L has at least one string x which doesn't have any partition(u, v, w) such that it satisfies the pumping lemma. The contradiction happened because our assumption that L is regular is FALSE. Therefore the language L is proven to be not regular.
If the R is not able to show the above, this is not a Proof of the language being Regular. It just means that L can be a Regular or Irregular language which just happens to satisfy the pumping lemma conditions.
Always remember, the pumping lemma is if(L is regular), then Statements. The vice-versa is not necessarily TRUE. Although it might be TRUE in some cases.
Therefore the pumping lemma is useful only if you want to prove that a language is not regular.
(Source: Theory of Computation(NPTEL): Prof. Somenath Biswas(IIT Kanpur)
Here's a homework problem:
Is L_4 Regular?
Let L_4 = L*, where L={0^i1^i | i>=1}.
I know L is non-regular and I know that Kleene Star is a closed operation, so my assumption is that L_4 is non-regular.
However my professor provided an example of the above in which L = {0^p | p is prime}, which he said was regular by proving that L* was equal to L(000* + e) by saying each was a subset of one another (e in this case means the empty word).
So his method involved forming a regex of 0^p, but how I can do that when I essentially have one already?
Regular languages are closed under Kleene star. That is, if language R is regular, so is R*.
But the reasoning doesn't work in the other direction: there are nonregular languages P for which P* is actually regular.
You mentioned one such P in your question: the set of strings 0^p where p is prime.
It is easy to use the pumping lemmas for regular and context-free languages to show that P is at least context-sensitive.
However, P* is equivalent to the language 0^q, where q is the sum of zero or more primes.
But this is true for q=0 (the empty string) and any q>=2, so P* can be recognized with a 3-state DFA, even though P itself is not regular.
So L being context-free has no bearing on whether your L_4 = L* is regular or not. If you can construct a DFA that recognizes L_4, as I did for P* above, then clearly it's regular.
In the process of trying to find a DFA that works, you'll probably see some pattern
emerge that can be used as the basis for a pumping argument. The Myhill-Nerode theorem is another approach to proving a language non-regular, and is useful if the language lends itself to analysis of prefixes and distinguishing extensions. If the language can be decomposed into a finite set of equivalence classes under a certain relation, then it can be recognized with a DFA containing that many states.
Edit: For anyone wondering whether OP's example L_4 is regular or not...it's not, which can be proved using the pumping lemma for regular languages.
Assume L_4 is regular, with "pumping length" P. Consider the string w=0P1P, which is an element of L_4. We need to decompose it into the form w=xyz,
with |y| >= 1 and |xy| <= P. Any choice of xy fulfilling these conditions will consist of all zeroes. But then any string w' = xynz with n != 1 will have mismatched counts of 0s and 1s, and therefore cannot be an element of L_4. So the pumping lemma does not hold, and L_4 cannot be regular.