Erlang List Comprehension of Cartesian Product - erlang

I'm learning Erlang and have come across/trying to understand list comprehension. I've discovered that you can make Cartesian products quite easily using it.
Basically I though of a deck of cards and that if you multiply the unique values by the number of suits, you will result will every possible combination - creating a full deck of cards. However, what if I wish to add the 2 jokers to the deck - but jokers do not belong to a suit. How do we solve that issue?
The code below is what I have so far and will output the possible combinations without the jokers.
CardValues = [ace, king, queen, jack, 10, 9, 8, 7, 6, 5, 4, 3, 2],
CardSuits = [spades,hearts,clubs,diamonds],
CartesianList = [{X, Y} || X <- CardValues, Y <- CardSuits ],
io:format("\nCartesianList:~p\n",[CartesianList]).
Would there be a better way of achieving/how would you achieve this?
I expect the output for the jokers would be something like {joker, nosuit}
Thanks,
Snelly.

If you really want to get it directly from a list comprehension, you may use filters:
CardValues = [joker,joker,ace, king, queen, jack, 10, 9, 8, 7, 6, 5, 4, 3, 2],
CardSuits = [spades,hearts,clubs,diamonds,nosuit],
CartesianList = [{X, Y} || X <- CardValues, Y <- CardSuits, ((X == joker)andalso(Y==nosuit))orelse((X =/= joker)andalso(Y=/=nosuit)) ],
io:format("\nCartesianList:~p\n",[CartesianList]).
But it is really weird, artificial and inefficient, I would add them manually:
CardValues = [ace, king, queen, jack, 10, 9, 8, 7, 6, 5, 4, 3, 2],
CardSuits = [spades,hearts,clubs,diamonds],
CartesianList = [{joker,nosuit},{joker,nosuit}|[{X, Y} || X <- CardValues, Y <- CardSuits ]]],
io:format("\nCartesianList:~p\n",[CartesianList]).

Related

How to generate conditions within constraints in Z3py

Let us assume there are 5-time slots and at each time slot, I have 4 options to choose from, each with a known reward, for eg. rewards = [5, 2, 1, -3]. At every time step, at least 1 of the four options must be selected, with a condition that, if option 3 (with reward -3) is chosen at a time t, then for the remaining time steps, none of the options should be selected. As an example, considering the options are indexed from 0, both [2, 1, 1, 0, 3] and [2, 1, 1, 3, 99] are valid solutions with the second solution having option 3 selected in the 3rd time step and 99 is some random value representing no option was chosen.
The Z3py code I tried is here:
T = 6 #Total time slots
s = Solver()
pick = [[Bool('t%d_ch%d' %(j, i)) for i in range(4)] for j in range(T)]
# Rewards of each option
Rewards = [5, 2, 1, -3]
# Select at most one of the 4 options as True
for i in range(T):
s.add(Or(Not(Or(pick[i][0], pick[i][1], pick[i][2], pick[i][3])),
And(Xor(pick[i][0],pick[i][1]), Not(Or(pick[i][2], pick[i][3]))),
And(Xor(pick[i][2],pick[i][3]), Not(Or(pick[i][0], pick[i][1])))))
# If option 3 is picked, then none of the 4 options should be selected for the future time slots
# else, exactly one should be selected.
for i in range(len(pick)-1):
for j in range(4):
s.add(If(And(j==3,pick[i][j]),
Not(Or(pick[i+1][0], pick[i+1][1], pick[i+1][2], pick[i+1][3])),
Or(And(Xor(pick[i+1][0],pick[i+1][1]), Not(Or(pick[i+1][2], pick[i+1][3]))),
And(Xor(pick[i+1][2],pick[i+1][3]), Not(Or(pick[i+1][0], pick[i+1][1]))))))
if s.check()==False:
print("unsat")
m=s.model()
print(m)
With this implementation, I am not getting solutions such as [2, 1, 1, 3, 99]. All of them either do not have option 3 or have it in the last time slot.
I know there is an error inside the If part but I'm unable to figure it out. Is there a better way to achieve such solutions?
It's hard to decipher what you're trying to do. From a basic reading of your description, I think this might be an instance of the XY problem. See https://xyproblem.info/ for details on that, and try to cast your question in terms of what your original goal is; instead of a particular solution, you're trying to implement. (It seems to me that the solution you came up with is unnecessarily complicated.)
Having said that, you can solve your problem as stated if you get rid of the 99 requirement and simply indicate -3 as the terminator. Once you pick -3, then all the following picks should be -3. This can be coded as follows:
from z3 import *
T = 6
s = Solver()
Rewards = [5, 2, 1, -3]
picks = [Int('pick_%d' % i) for i in range(T)]
def pickReward(p):
return Or([p == r for r in Rewards])
for i in range(T):
if i == 0:
s.add(pickReward(picks[i]))
else:
s.add(If(picks[i-1] == -3, picks[i] == -3, pickReward(picks[i])))
while s.check() == sat:
m = s.model()
picked = []
for i in picks:
picked += [m[i]]
print(picked)
s.add(Or([p != v for p, v in zip(picks, picked)]))
When run, this prints:
[5, -3, -3, -3, -3, -3]
[1, 5, 5, 5, 5, 1]
[1, 2, 5, 5, 5, 1]
[2, 2, 5, 5, 5, 1]
[2, 5, 5, 5, 5, 1]
[2, 1, 5, 5, 5, 1]
[1, 1, 5, 5, 5, 1]
[2, 1, 5, 5, 5, 2]
[2, 5, 5, 5, 5, 2]
[2, 5, 5, 5, 5, 5]
[2, 5, 5, 5, 5, -3]
[2, 1, 5, 5, 5, 5]
...
I interrupted the above as it keeps enumerating all the possible picks. There are a total of 1093 of them in this particular case.
(You can get different answers depending on your version of z3.)
Hope this gets you started. Stating what your original goal is directly is usually much more helpful, should you have further questions.

Keras Tokenizer num_words doesn't seem to work

>>> t = Tokenizer(num_words=3)
>>> l = ["Hello, World! This is so&#$ fantastic!", "There is no other world like this one"]
>>> t.fit_on_texts(l)
>>> t.word_index
{'fantastic': 6, 'like': 10, 'no': 8, 'this': 2, 'is': 3, 'there': 7, 'one': 11, 'other': 9, 'so': 5, 'world': 1, 'hello': 4}
I'd have expected t.word_index to have just the top 3 words. What am I doing wrong?
There is nothing wrong in what you are doing. word_index is computed the same way no matter how many most frequent words you will use later (as you may see here). So when you will call any transformative method - Tokenizer will use only three most common words and at the same time, it will keep the counter of all words - even when it's obvious that it will not use it later.
Just a add on Marcin's answer ("it will keep the counter of all words - even when it's obvious that it will not use it later.").
The reason it keeps counter on all words is that you can call fit_on_texts multiple times. Each time it will update the internal counters, and when transformations are called, it will use the top words based on the updated counters.
Hope it helps.
Limiting num_words to a small number (eg, 3) has no effect on fit_on_texts outputs such as word_index, word_counts, word_docs. It does have effect on texts_to_matrix. The resulting matrix will have num_words (3) columns.
>>> t = Tokenizer(num_words=3)
>>> l = ["Hello, World! This is so&#$ fantastic!", "There is no other world like this one"]
>>> t.fit_on_texts(l)
>>> print(t.word_index)
{'world': 1, 'this': 2, 'is': 3, 'hello': 4, 'so': 5, 'fantastic': 6, 'there': 7, 'no': 8, 'other': 9, 'like': 10, 'one': 11}
>>> t.texts_to_matrix(l, mode='count')
array([[0., 1., 1.],
[0., 1., 1.]])
Just to add a little bit to farid khafizov's answer,
words at sequence of num_words and above are removed from the results of texts_to_sequences (4 in 1st, 5 in 2nd and 6 in 3rd sentence disappeared respectively)
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
print(tf.__version__) # 2.4.1, in my case
sentences = [
'I love my dog',
'I, love my cat',
'You love my dog!'
]
tokenizer = Tokenizer(num_words=4)
tokenizer.fit_on_texts(sentences)
word_index = tokenizer.word_index
seq = tokenizer.texts_to_sequences(sentences)
print(word_index) # {'love': 1, 'my': 2, 'i': 3, 'dog': 4, 'cat': 5, 'you': 6}
print(seq) # [[3, 1, 2], [3, 1, 2], [1, 2]]

How to get a list of integers from a given set of possible integers in z3?

Minimal example is the following: Given a set of possible integers [1, 2, 3] create an arbitrary list of size 5 using z3py. Duplicates are allowed.
The expected result is something like [1, 1, 1, 1, 1] or [3, 1, 2, 2, 3], etc.
How to tackle this problem and how to implement 'choosing'? Finally, I would like to find all solutions which can be done by adding additional constraints as explained in link. Any help will be very appreciated.
The following should work:
from z3 import *
def choose(elts, acceptable):
s = Solver()
s.add(And([Or([x == v for v in acceptable]) for x in Ints(elts)]))
models = []
while s.check() == sat:
m = s.model ()
if not m:
break
models.append(m)
block = Not(And([v() == m[v] for v in m]))
s.add(block)
return models
print choose('a b c d e', [1, 2, 3])

How to remove array elements and append it to the front of the array in ruby without using any inbuilt methods?

I have an array say [1,2,3,4,5,6,7,8]. I need to take an input from the user and remove the last input number of array elements and append it to the front of the array. This is what I have achieved
def test(number, array)
b = array - array[0...(array.length-1) - number]
array = array.unshift(b).flatten.uniq
return array
end
number = gets.chomp_to_i
array = [1,2,3,4,5,7,8,9]
now passing the argument to test gives me the result. However, there are two problems here. first is I want to find a way to do this append on the front without any inbuilt method.(i.e not using unshift).Second, I am using Uniq here, which is wrong since the original array values may repeat. So how do I still ensure to get the correct output? Can some one give me a better solution to this.
The standard way is:
[1, 2, 3, 4, 5, 7, 8, 9].rotate(-3) #=> [7, 8, 9, 1, 2, 3, 4, 5]
Based on the link I supplied in the comments, I threw this together using the answer to that question.
def test(number, array)
reverse_array(array, 0, array.length - 1)
reverse_array(array, 0, number - 1)
reverse_array(array, number, array.length - 1)
array
end
def reverse_array(array, low, high)
while low < high
array[low], array[high] = array[high], array[low]
low += 1
high -= 1
end
end
and then the tests
array = [1,2,3,4,5,7,8,9]
test(2, array)
#=> [8, 9, 1, 2, 3, 4, 5, 7]
array = [3, 4, 5, 2, 3, 1, 4]
test(2, array)
#=> [1, 4, 3, 4, 5, 2, 3]
Which I believe is what you're wanting, and I feel sufficiently avoids ruby built-ins (no matter what way you look at it, you're going to need to get the value at an index and set a value at an index to do this in place)
I want to find a way to do this append on the front without any inbuilt method
You can decompose an array during assignment:
array = [1, 2, 3, 4, 5, 6, 7, 8]
*remaining, last = array
remaining #=> [1, 2, 3, 4, 5, 6, 7]
last #=> 8
The splat operator (*) gathers any remaining elements. The last element will be assigned to last, the remaining elements (all but the last element) are assigned to remaining (as a new array).
Likewise, you can implicitly create an array during assignment:
array = last, *remaining
#=> [8, 1, 2, 3, 4, 5, 6, 7]
Here, the splat operator unpacks the array, so you don't get [8, [1, 2, 3, 4, 5, 6, 7]]
The above moves the last element to the front. To rotate an array n times this way, use a loop:
array = [1, 2, 3, 4, 5, 6, 7, 8]
n = 3
n.times do
*remaining, last = array
array = last, *remaining
end
array
#=> [6, 7, 8, 1, 2, 3, 4, 5]
Aside from times, no methods were called explicitly.
You could create a new Array with the elements at the correct position thanks to modulo:
array = %w[a b c d e f g h i]
shift = 3
n = array.size
p Array.new(n) { |i| array[(i - shift) % n] }
# ["g", "h", "i", "a", "b", "c", "d", "e", "f"]
Array.new() is a builtin method though ;)

Calculate differences between array elements

Given a sorted array of n integers, like the following:
ary = [3, 5, 6, 9, 14]
I need to calculate the difference between each element and the next element in the array. Using the example above, I would end up with:
[2, 1, 3, 5]
The beginning array may have 0, 1 or many elements in it, and the numbers I'll be handling will be much larger (I'll be using epoch timestamps). I've tried the following:
times = #messages.map{|m| m.created_at.to_i}
left = times[1..times.length-1]
right = times[0..times.length-2]
differences = left.zip(right).map { |x| x[0]-x[1]}
But my solution above is both not optimal, and not ideal. Can anyone give me a hand?
>> ary = [3, 5, 6, 9, 14] #=> [3, 5, 6, 9, 14]
>> ary.each_cons(2).map { |a,b| b-a } #=> [2, 1, 3, 5]
Edit:
Replaced inject with map.
Similar but more concise:
[3, 5, 6, 9, 14].each_cons(2).collect { |a,b| b-a }
An alternative:
a.map.with_index{ |v,i| (a[i+1] || 0) - v }[0..-2]
Does not work in Ruby 1.8 where map requires a block instead of returning an Enumerator.

Resources