Ruby boolean logic: some amount of variables are true - ruby

Let say I have 3 variables: a, b, c.
How can I check that just zero or one of them is true?

[a, b, c].count(true) < 2
.....................

Related

Algorithm: generate list permutation by preference

I have a function f that takes a list of items as it's single parameter and returns true if the ordering of the items is accepted or false if the ordering of the items is not accepted.
There exists at least one or more permutations of list l which f(l) returns true.
Function f is a black box (we don't have it's source code) and the type of the elements held by list l are also unknown or generic.
p is a permutation of list l according to user preferences. The most preferred item has index 0 the least preferred item has index l.size()-1
list p will always contain all elements of list l.
The goal is to find a permutation of l let's call it p_accepted where f(p_accepted) returns true and preference p is maximized.
Here's an example
given l = [a, b, c, d, e, f]
given p = [c, a, f, b, e, d]
given f([ a, b, c, d, e, f ]) = false
given f([ c, a, f, b, e, d ]) = false
given f([ d, e, b, f, a, c ]) = true
given f([ f, e, d, c, b, a ]) = true
given f([ c, b, f, a, d, e ]) = true
given f([ a, c, f, b, e, d ]) = true
given f([ anything else ]) = false
the expected output for p_accepted is [c, b, f, a, d, e]
it is accepted because f(p_accepted) returns true and no other permutation of l ranks the item 'c' as high. item 'c' is the most preferred by the user since it has index 0
Implementations in pseudo code or any language are accepted.
[EDIT]
Clarifications
list p will always contain all elements of list l
list l items can only be compared by identity, i.e.: by reference
so an item in list p can be found in list l by l[i] == p[j]
list l items cannot always be compared like in the example where a compare function c might determine that a < b i.e.: c('a', 'b') = 1.
[EDIT 2]
To understand preferences better
Imagine Alice and Bob being forced to do 4 tasks together at the same time in order. [task a, task b, task c, task d].
Alice has one preferred order for doing the tasks [a,b,c,d]. Bob has two preferred orders for doing the tasks [a,c,b,d], [a,d,b,c]. If you are Alice, the function f would return true only for [a,c,b,d] and [a,d,b,c] which are Bob's preferences, since both like to do task a first p_accepted should start with a.
Note that this is an analogy function f does not accept permutations based on multiple user's order preference.

Constraint-programming: Fill grid with colors following pattern rules

I'm new to constraint-programming (coming from c#) and I'm trying to solve this problem. Unfortunately I don't have a name for this kind of puzzle so I'm not sure what to search for. The closest examples I can find are Nonogram and Tomography puzzles.
Puzzle description:
The player is given an empty game board (varying size) that they must fill with n-colors, using clue patterns for the rows and columns. Each clue pattern is the sequence of colors in that row/col but with consecutive duplicates removed.
Here is an example easy small 4x4 grid with 3 colors:
rbg,rbr,grb,bgbg <- (top-to-bottom column constraints)
_,_,_,_ rgb <- (row constraints)
_,_,_,_ brg
_,_,_,_ b
_,_,_,_ grbg
Solutions (2):
r,r,g,b
b,?,r,g
b,b,b,b
g,r,b,g
? Can be either red or blue but not green.
Pattern examples below.
Examples given 6-length sequences to pattern:
aaaaaa -> a
aabbcc -> abc
abbbbc -> abc
cabbbc -> cabc
bbbaac -> bac
abbaab -> abab
abcabc -> abcabc
Examples given pattern to potential solution sequences:
abc -> abc (3 length solution)
abc -> abcc, abbc, aabc (4 length solutions)
abc -> abccc, abbcc, abbbc, aabbc, aaabc (5 length solutions)
I've tried to solve it in C# or-tools and MiniZinc but the biggest problem I have is building the constraints. I can generate the patterns from a sequence (in c# imperative way) but then how to turn that into a constraint?
How I'm thinking about it: generate all potential sequences from each clue pattern. Then make a constraint for the corresponding row/col that says it must be one of those sequences.
Example from top row in above puzzle: rgb to [4-length sequences] -> rgbb, rggb, rrgb, and then add a constraint for that row: must equal one of these sequences.
Am I thinking about this right? Any smarter ways to do it?
Thanks for any advice.
=====================================
Edit after some progress:
This MiniZinc correctly solves the top row for the pattern abc which has 3 solutions of 4 length: aabc, abbc, abcc.
include "globals.mzn";
array [1..4, 1..4] of var 1..3: colors;
constraint regular(row(colors, 1), 4, 3,
[|
% a, b, c
2,0,0| % accept 'a'
2,3,0| % accept 'a' or 'b' ?
0,3,4| % accept 'b' or 'c' ?
0,0,4| % accept 'c'
|], 1, {4});
% Don't care about rest of grid for now.
constraint forall(i,j in 1..4 where i > 1) (row(colors, i)[j] = 1);
solve satisfy;
output [show(colors)];
However I'm not sure how to handle larger grids with many patterns other than hardcoding everything like this. I will experiment a bit more.
The constraints you are talking about seem to be easily represented as regular expressions. For example your abc example with varying length can be caught using the regular expression abc.*, which requires one a then one b, and then one c, it will accept anything else afterwards.
In MiniZinc these kinds of constraints are expressed using the regular predicate. The regular predicate simulates an automaton with accepting states. By providing the allowed state-transitions the model is constraint.
The example expression abc.* would be enforced by the following constraint item:
% variables considered, nr states, input values
constraint regular(VARS, 4, 1..3, [|
% a, b, c
2,0,0| % accept 'a'
0,3,0| % accept 'b'
0,0,4| % accept 'c'
4,4,4| % accept all
|], 1, {4}); % initial state, accepting states
In Prolog(language), I use DCG form to describe such problems. It is extended BNF form.
So I suggest finding approach with Extended BNF Form in your environment.
SWI-Prolog example:
color_chunk_list(Encoded,Decoded):-
phrase(chunk_list(Encoded),Decoded),
chk_continuity(Encoded).
chunk_list([])-->[].
chunk_list([First|Rest])-->colorrow(First),chunk_list(Rest).
colorrow(Color)-->[Color],colorrow(Color).
colorrow(Color)-->[Color].
chk_continuity([First,Second|Rest]):-First \= Second,chk_continuity([Second|Rest]).
chk_continuity([_]).
In this program, encodings and decodings are bidirectional.
Tests:
?- length(L,4),color_chunk_list([r,g],L).
L = [r, r, r, g] ;
L = [r, r, g, g] ;
L = [r, g, g, g] ;
false.
?- length(L,6),color_chunk_list([a,b,c],L).
L = [a, a, a, a, b, c] ;
L = [a, a, a, b, b, c] ;
L = [a, a, a, b, c, c] ;
L = [a, a, b, b, b, c] ;
L = [a, a, b, b, c, c] ;
L = [a, a, b, c, c, c] ;
L = [a, b, b, b, b, c] ;
L = [a, b, b, b, c, c] ;
L = [a, b, b, c, c, c] ;
L = [a, b, c, c, c, c] ;
false.
?- color_chunk_list(L,[a,a,b,b,c,c]).
L = [a, b, c] ;
false.
?- color_chunk_list(L,[b,r,b,r,r,g,g,b]).
L = [b, r, b, r, g, b] ;
false.
In ECLiPSe, which is prolog based CLP system (not IDE one),
above predicate(color_chunk_list) can be turned into clp constraint
with propia mechanism and can genarate clp propagation.

Equality test on three or more objects

If I have three or more objects like so:
a = 4
b = 4
c = 4
d = 2
what would be a clean ruby-style way of determining whether they are all equal? Any bespoke methods for running equality tests on three or more elements?
I suppose I could do something like this:
arrays = [a,b,c,d].map{|x| [x]}
arrays.first == arrays.reduce(:&) ? true : false
which appears to work, but feels sort of ham handed, and might be difficult for other developers to read.
[a,b,c,d].any?{|x| x != a}
or
array.any?{|x| x != array.first}
Alternatively, the #all? method may read more intuitively for some:
array.all? {|x| x == array.first }
[a, b, c, d].group_by(&:itself).length == 1
# => false
or
[a, b, c, d].chunk(&:itself).to_a.length == 1
# => false
or
[a, b, c, d].chunk_while(&:==).to_a.length == 1
# => false
or the naive:
[a, b, c, d].uniq.length == 1
I was reminded of one?. Provided that you do not have any falsy element, the above can be written:
[a, b, c, d].uniq.length.one?
I think the answer by #kipar is better by all means, but for the sake of “doing it the way you started” I would post this here:
[a, b, c, d].reduce { |r, e| r == e && r } && true

Prolog program to recognize context free grammar a^n b^n

Using Prolog I'm trying to write a predicate that recognizes context free grammar and returns true if the input list matches the CFG.
The alphabet of the input consists only of a,b.
The CFG i'm trying to match is
S-> TT
T -> aTb | ab
I'm not quite sure how to implement this, mainly the T rule.
s(S0,S):-t(S0,S),t(S1,S).
t(S0,S):-S0 = a, t(S1,S), S1 = b; S0 = a, S1 = b.
match([H|T] :- s(H,T).
So if I query [a, a, b, b] it should return true.
However, I'm just getting an infinite loop.
I'm not quite sure how to implement the a^n b^n rule.
I would write the CFG in this way:
S -> T
T -> a T b | {epsilon}
that translates directly to a DCG:
s --> t.
t --> [].
t --> a, t, b.
Note I swapped the epsilon rule, to get the ability to generate phrases.
Translating that DCG by hand :
s(S0,S) :- t(S0,S).
t(S0,S0).
t(S0,S) :- S0=[a|S1], t(S1,S2), S2=[b|S].
Yields
?- phrase(s,L).
L = [] ;
L = [a, b] ;
L = [a, a, b, b] ;
L = [a, a, a, b, b, b] ;
...

Prolog - return value from base case

Ok, here's the deal:
I've got two piles of shirts
I want to take a random shirt from each pile and put them in a new pile
Then get the new pile out
And here is the code:
mix([],[],_).
mix(P1,P2, Pile):-
takeshirt(P1,1,Taken1,Rem1), takeshirt(P2,1,Taken2,Rem2), #Take one
append(Pile,Taken1,New), append(New,Taken2,NewPile), #Put both of them
mix(Remain1,Remain2,NewPile).
This is what the result look like:
1 ?- mix([a,b],[c,d],NewPile).
NewPile = [] .
I want it to look like:
1 ?- mix([a,b],[c,d],NewPile).
NewPile = [b, d, a, c] .
Or whatever the result is. I checked via the graphical debugger and found out that when the final call to mix happens, the bindings are:
P1 = Taken1 = [b]
P2 = Taken2 = [c]
Pile = [a, d]
Rem1 = Rem2 = []
New = [a, d, b]
NewPile = [a, d, b, c] #<--- Interresting
So the wanted value is in NewPile when the final call to:
mix([],[],_).
happens. After this is it collapses like a house of cards.
So the question is:
mix([],[],_).
I'd like to return the _ value from the base case, this rule mix is actually used from a higher instance where I send in two piles and get the new pile out.
Update:
To clarify some comments about the takeshirt rule, here it is:
takeshirt(_,0,[],_).
takeshirt(List,Number,[Element|Taken],Remain) :- N > 0,
length(List,Len),
Index is random(Len) + 1,
removeshirt_at(Element,List,Index,Remain),
Number1 is Number - 1,
takeshirt(Remain,Number1,Taken,Remain).
Consider the following modifications to your code:
mix([], [], []) :- !.
mix(P1, P2, Pile) :-
takeshirt(P1, 1, Taken1, Rem1),
takeshirt(P2, 1, Taken2, Rem2),
append(Taken1, Taken2, Pile0),
mix(Rem1, Rem2, Pile1),
append(Pile0, Pile1, Pile).
It seems you need to accumulate the 'shirts' (as list atoms). Here, we are recursively appending them onto the third argument of mix/3 (Pile), until the base case (the first clause) is hit when both input lists are empty lists (note that the cut ! is necessary here as the binding pattern for the second clause matches the first, so we want to exclude it). The behaviour of the second clause, which takes a shirt from each input list for every step, requires that they must have been of equal length to start with.
To test this, I used the following definition of takeshirt/4:
takeshirt(Ps, _, [P], Rem) :-
select(P, Ps, Rem).
Note that the second argument here is unused, as select/3 is being used to take a single element (a shirt) from the list, and return the remainder. The absence of a cut (!) after the select allows this predicate to backtrack in selecting all other elements (shirts) from the list. If we now execute your example query with this definition, we can get:
1 ?- mix([a,b],[c,d],NewPile).
NewPile = [a, c, b, d] ;
NewPile = [a, d, b, c] ;
NewPile = [b, c, a, d] ;
NewPile = [b, d, a, c] ;
false.
...we can see that mix/3 enumerates all possible 'piles' on backtracking by taking a shirt from the first pile (first input list), then a shirt from the second pile (second input list), and so on, until both input lists are empty. If your definition of takeshirt/4 doesn't leave choice-points, (is non-backtracking), then you could only get one solution, if any.

Resources