I need to do something like the following
e = []
m = []
p = []
t = []
...and so on for about 10 different arrays
Is there a way to create all these arrays on one line?
You can do it using the following:
e,m,p,t... = Array.new(10) { [] }
It turns out
[[]]*10
is not the right way to go, [[]]*10 is for repetition and is just repeating the same object [] 10 times, so all the variables would end up getting assigned to the same object.
Like multiple variable declaration in one line a1, a2, a3 = 3, 10, 4
e, m, p, t ... = [], [], [], [] ...
I'm curious at what are those 10 different arrays, because I would suspect they shouldn't be 10 different variables but just one. You don't give any context, so I can only guess, something like the following might better:
whatever = Hash.new{|h, k| h[k] = []}
whatever[:e] # => []
whatever[:m] << 42
whatever[:m] # => [42]
# etc...
Otherwise, as zomboid wrote:
e, m, p, t ... = [], [], [], [] ...
What all fails
> p, q, r = v = Array.new(3, [])
=> [[], [], []]
> v.map(&:object_id)
=> [70155104393020, 70155104393020, 70155104393020]
> p = q = r = []
=> []
> [p, q, r].map(&:object_id)
=> [70155104367380, 70155104367380, 70155104367380]
What works
> p, q, r = v = Array.new(3){ [] }
=> [[], [], []]
> v.map(&:object_id)
=> [70155104731780, 70155104731760, 70155104731740]
Related
I'm trying to write a predicate that determines whether the first list have the same elements with either two other lists in Prolog. This is what I have tried:
same([],[],[]).
same([A|As],[B|Bs],[C|Cs]) :- A = B, A = C, common(As,Bs,Cs).
The output is supposed to be something like this:
?- same(E,[1,6,8,2,3],[3,7,9,10,2]).
E = [] ;
E = [2] ;
E = [2, 3] ;
E = [3] ;
false.
I have no idea where I went wrong here. Any help would be much appreciated!
Your procedure will succeed only when the three lists have the same length and every item from the first list unifies with the other corresponding items in the remaining lists. That is, if lists are ground it will only succeed if the three lists are the same.
You may try something like this:
same([], _, _).
same([A|As], Bs, Cs):-
append(_, [A|Bs1], Bs),
select(A, Cs, Cs1),
same(As, Bs1, Cs1).
where the recursive step "takes" an item from the second list and selects it from the the third one.
sample run:
?- same(E,[1,6,8,2,3],[3,7,9,10,2]).
E = [] ;
E = [2] ;
E = [2, 3] ;
E = [3] ;
false.
I was thinking I can solve SLD trees till I found this question in past papers.
Which predicate will be picked for the first time?
I assume it is the third rule, but could someone explain to me how to approach this question, by simply showing a procedure of solving swap([1,2], U)
How do we unify ([S,H|U]) with U?
EDIT
Assuming I tried to unify:
swap([H,S|T], [S,H|U]) with swap([1,2], U)
[H,S|T] = [1,2], [S,H|U] = U
H = 1, S = 2, T = [], [S,H|U] = U
H = 1, S = 2, T = [], [2,1|U] = U
H = 1, S = 2, T = [], U = [2,1|U]
and I end up with swap([], U']) but how does this unify with 3 given facts/rules in order to result in U = [2,1]
When selecting a predicate's clause from the knowledge base you're supposed to rename its variables, consistently, so that they are all "fresh", i.e. new, i.e. no new name in the selected clause was yet seen in the process. For instance,
solving: swap([1,2], U).
selecting:
-> swap([], []).
<- doesn't match
-> swap([H0], [H0]).
<- doesn't match
-> swap([H1,S1|T1], [S1,H1|U1]) :- swap( T1, U1).
= matches, with
{ [H1,S1|T1] = [1,2]
, [S1,H1|U1] = U }
i.e.
{ H1 = 1, S1 = 2, T1 = [], U = [2,1|U1] }
-> now solve the body
swap( T1, U1)
i.e.
swap( [], U1)
->
........
To finish up the example you have to solve swap( [], U1) by the same procedure as in this answer, selecting each of the three clauses of the predicate swap/2:
swap([], []). (does it match swap( [], U1)?)
yes, it does, unifying U1 = [].
this is then used in the unification for U, i.e.
U = [S1,H1|U1] = [2,1|U1] = [2,1|[]] = [2,1].
swap([H2],[H2]). (does it match swap( [], U1)?)
etc.
If course you could rename the vars as anything, like swap([A99],[A99])., as long as the renaming is consistent (i.e. rename a variable only once, and use the new name in place of the old one, consistently).
([S,H|U]) and U are not supposed to share the variable U. Before applying a rule, you have to 'freshen' its variables, e.g. by adding an underscore or prime. You would then unify ([S',H'|U']) and U.
call((append(As,Bs,[1,2,3,4]),writeq(user,append(As,Bs,[1,2,3,4])))).
Result:
append([],[1,2,3,4],[1,2,3,4])
As = [],
Bs = [1,2,3,4] ? ;
append([1],[2,3,4],[1,2,3,4])
As = [1],
Bs = [2,3,4] ? ;
append([1,2],[3,4],[1,2,3,4])
As = [1,2],
Bs = [3,4] ? ;
append([1,2,3],[4],[1,2,3,4])
As = [1,2,3],
Bs = [4] ? ;
append([1,2,3,4],[],[1,2,3,4])
As = [1,2,3,4],
Bs = [] ? ;
no
But if I try this:
call((append(As,Bs,[1,2,3,4]) -> writeq(append(As,Bs,[1,2,3,4])) ; writeq('There are no solutions.\n'))).
It gives back this:
append([],[1,2,3,4],[1,2,3,4])
As = [],
Bs = [1,2,3,4] ? ;
no
What is the difference? I try to write it so that it can tell if there are 0 solutions.
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
If I initialize objects with assignment like a = b = c = []
then this variables have the same object_ids: a.object_id == b.object_id == c.object_id
Also I tried:
[a, b, c].map {|e| e = [] }
a, b, c = Array.new(3, [])
a, b, c = Array.new(3, Array.new)
but it doensn't initialize a, b, c variables with different object_ids
Is there a way to initialize variables a, b, c with different object ids but with the same value == []?
How about these possible solutions:
a,b,c=[],[],[]
a,b,c=(0..2).map{[]}
a,b,c=Array.new(3){[]}
How about this?
a = []
b = []
c = []