Related
I am attempting to write a function in Scala that takes a valid Latin Square as input and then returns a Boolean value indicating whether the input Latin Square is a valid instance of an operation-table for the Damm Algorithm, or not. The Damm Algorithm appears to be of the "Check digit" class of error detection mechanisms.
The desired function is an implementation of the implication described in the Design section of the Wikipedia article for the Damm Algorithm. The implication is captured by the assertion of:
a weak totally anti-symmetric quasigroup with the property x ∗ x = 0
I'm insufficient in both the math skills to properly read and interpret Damm's paper, and then having enough German (the language within which the paper was written) reading skills to be able to confidently interpret how I would encode a correct validation function.
Given the following function definition:
def validate(latinSquare: List[List[Int]]): Boolean =
???
With what would I replace the ????
Within the paper, a single instance of a valid 10x10 Latin Square is provided. It is reproduced within the Wikipedia article and looks like this:
|0 1 2 3 4 5 6 7 8 9
-+-------------------
0|0 3 1 7 5 9 8 6 4 2
1|7 0 9 2 1 5 4 8 6 3
2|4 2 0 6 8 7 1 3 5 9
3|1 7 5 0 9 8 3 4 2 6
4|6 1 2 3 0 4 5 9 7 8
5|3 6 7 4 2 0 9 5 8 1
6|5 8 6 9 7 2 0 1 3 4
7|8 9 4 5 3 6 2 0 1 7
8|9 4 3 8 6 1 7 2 0 5
9|2 5 8 1 4 3 6 7 9 0
I can see there are others who have sought an answer to this. However, no one has yet provided a requested code-based valid Latin Square solution.
I have coded up a generic Latin Square generator, but need the above validation function which will serve as the filter to eliminate each candidate Latin Square that does not meet the necessary condition(s) of the above implication.
In functional programming terms, the checksum algorithm is foldLeft with a carefully chosen binary operation. The requirements for this binary operation, in English:
In every two-digit input, if we change one of the digits, then the checksum changes (Latin square…);
In every three-digit input, if the latter two digits are distinct and we swap them, then the checksum changes (…with weak total antisymmetry);
The Latin square has zeros on the diagonal.
In Python 3:
def validate(latinSquare):
Q = range(len(latinSquare))
return all(
x == y
for c in Q
for x in Q
for y in Q
if latinSquare[latinSquare[c][x]][y] == latinSquare[latinSquare[c][y]][x]
) and all(latinSquare[x][x] == 0 for x in Q)
print(
validate(
[
[0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
[7, 0, 9, 2, 1, 5, 4, 8, 6, 3],
[4, 2, 0, 6, 8, 7, 1, 3, 5, 9],
[1, 7, 5, 0, 9, 8, 3, 4, 2, 6],
[6, 1, 2, 3, 0, 4, 5, 9, 7, 8],
[3, 6, 7, 4, 2, 0, 9, 5, 8, 1],
[5, 8, 6, 9, 7, 2, 0, 1, 3, 4],
[8, 9, 4, 5, 3, 6, 2, 0, 1, 7],
[9, 4, 3, 8, 6, 1, 7, 2, 0, 5],
[2, 5, 8, 1, 4, 3, 6, 7, 9, 0],
]
)
)
This is a conversion into Scala of the Python 3 Answer that was provided by David Eisenstat's answer.
View in Scastie:
def isValidDammOperationTable(validLatinSquare: List[List[Int]]): Boolean = {
val indices = validLatinSquare.indices.toList
(
indices.forall(index => validLatinSquare(index)(index) == 0)
&& indices.forall(
c =>
indices.forall(
x =>
indices.forall(
y =>
(validLatinSquare(validLatinSquare(c)(x))(y) != validLatinSquare(validLatinSquare(c)(y))(x))
|| (x == y)
)
)
)
)
}
val exampleLatinSquareX10: List[List[Int]] =
List(
List(0, 3, 1, 7, 5, 9, 8, 6, 4, 2)
, List(7, 0, 9, 2, 1, 5, 4, 8, 6, 3)
, List(4, 2, 0, 6, 8, 7, 1, 3, 5, 9)
, List(1, 7, 5, 0, 9, 8, 3, 4, 2, 6)
, List(6, 1, 2, 3, 0, 4, 5, 9, 7, 8)
, List(3, 6, 7, 4, 2, 0, 9, 5, 8, 1)
, List(5, 8, 6, 9, 7, 2, 0, 1, 3, 4)
, List(8, 9, 4, 5, 3, 6, 2, 0, 1, 7)
, List(9, 4, 3, 8, 6, 1, 7, 2, 0, 5)
, List(2, 5, 8, 1, 4, 3, 6, 7, 9, 0)
)
println(isValidDammOperationTable(exampleLatinSquareX10)) //prints "true"
Quite often, I have to generate sequences of numbers in some semi-random way, which means that it is not totally random, but has to have some other property. For example we need a random sequence of 1,2,3 and 4s, but no number must be repeated three times in a row. These are usually not very complicated to do, but I ran into a tricky one: I need to generate a semi-random sequence that is a bit over 400 long, is composed of 1,2,3 and 4s, each number must appear the same amount of times (or if the sum is not divisible by four than as close as you can get it) and they must not repeat 3 times in a row (so 1,3,4,4,4,2 is not ok ).
I tried to methods:
Create a list which has the desired length and number of numbers; shuffle; check if ok for consecutive numbers if not, shuffle again.
Create a list which has the desired length and number of numbers; generate all permutations and select which are ok; save these for later and randomly select one of them when needed.
Method number one runs for minutes before yielding any sequence that is ok and method number two generates so many permutations my jupter notebook gave up.
Here's the python code for the first one
from random import shuffle
v = []
for x in range(108):
v += [1,2,3,4]
shouldicontinue = 1
while shouldicontinue:
shuffle(v)
shouldicontinue = 0
for h in range(len(v)-1):
if v[h] == v[h+1] and v[h] == v[h+2]:
shouldicontinue = 1
break
else:
pass
and the second one
from random import shuffle
import itertools
v = []
for x in range(108):
v += [1,2,3,4]
good = []
for l in itertools.permutations(v):
notok = 0
for h in range(len(v)-1):
if v[h] == v[h+1] and v[h] == v[h+2]:
notok = 1
break
else:
pass
if not notok:
good.append(v)
I'm looking for a way to solve this problem in an efficient way, i.e.: if it runs in real time, it doesn't need more than say a minute to generate on slower computers or if it is prepared in advance in someway (like the idea of method 2), it can be prepared on some moderate level computer in a few hours.
Before you can check all the permutations of a >400 length list, the universe will likely have died. Thus you need another approach.
Here, I recommend trying to insert the elements in the list at random, but shifting to the next index when the insertion would break one of the requirements.
Cycling through your elements, 1 to 4 in your case, should ensure an insertion is always possible.
from itertools import cycle, islice
from random import randint
def has_repeated(target, n, lst):
"""A helper to check if insertion would break the max repetition requirement"""
count = 0
for el in lst:
count += el == target
if count == n:
return True
return False
def sequence(length, max_repeat, elements=(1, 2, 3, 4)):
# Iterator that will yield our elements in cycle
values = islice(cycle(elements), length)
seq = []
for value in values:
# Pick an insertion index at random
init_index = randint(0, len(seq))
# Loop over indices from that index until a legal position is found
for shift in range(len(seq) + 1):
index = init_index - shift
slice_around_index = seq[max(0, index - max_repeat):index + max_repeat]
# If the insertion would cause no forbidden subsequence, insert
if not has_repeated(value, max_repeat, slice_around_index):
seq.insert(index, value)
break
# This will likely never happen, except if a solution truly does not exist
else:
raise ValueError('failed to generate the sequence')
return seq
Sample
Here is some sample output to check the result is correct.
for _ in range(10):
print(sequence(25, 2))
Output
[4, 1, 4, 1, 3, 2, 1, 2, 4, 1, 4, 2, 1, 2, 2, 4, 3, 3, 1, 4, 3, 1, 2, 3, 3]
[3, 1, 3, 2, 2, 4, 1, 2, 2, 4, 3, 4, 1, 3, 4, 3, 2, 4, 4, 1, 1, 2, 1, 1, 3]
[1, 3, 2, 4, 1, 3, 4, 4, 3, 2, 4, 1, 1, 3, 1, 2, 4, 2, 3, 1, 1, 2, 4, 3, 2]
[1, 3, 2, 4, 1, 2, 2, 1, 2, 3, 4, 3, 2, 4, 2, 4, 1, 1, 3, 1, 3, 4, 1, 4, 3]
[4, 1, 4, 4, 1, 1, 3, 1, 2, 2, 3, 2, 4, 2, 2, 3, 1, 3, 4, 3, 2, 1, 3, 1, 4]
[2, 3, 3, 1, 3, 3, 1, 2, 1, 2, 1, 2, 3, 4, 4, 1, 3, 4, 4, 2, 1, 1, 4, 4, 2]
[3, 2, 1, 4, 3, 2, 3, 1, 4, 1, 1, 2, 3, 3, 2, 2, 4, 1, 1, 2, 4, 1, 4, 3, 4]
[4, 4, 3, 1, 4, 1, 2, 2, 4, 4, 3, 2, 2, 3, 3, 1, 1, 2, 1, 1, 4, 1, 2, 3, 3]
[1, 4, 1, 4, 4, 2, 4, 1, 1, 2, 1, 2, 2, 3, 3, 2, 2, 3, 1, 4, 4, 3, 3, 1, 3]
[4, 3, 2, 1, 4, 1, 1, 2, 2, 3, 3, 1, 4, 4, 1, 3, 2, 3, 4, 2, 1, 1, 4, 2, 3]
Efficiency-wise, it takes around 10ms to generate a list of length 10,000 with he same requirements. Hinting that this might be an efficient enough solution for most purpose.
I think it should be possible (with about 4 gigabytes of memory and 1 minute of precomputation) to generate uniformly distributed random sequences faster than 1 second per random sequence.
The idea is to prepare a cache of results for the question "How many sequences with exactly a 1s, b 2s, c 3s, d 4s are there which end with count copies of a particular digit?".
Once you have this cache, then you can compute how many sequences (N) there are that satisfy your constraint, and can generate one at random by picking a random number n between 1 and N and using the cache to generate the n^th sequence.
To save memory in the cache you can use a couple of tricks:
The answer is symmetric in a/b/c/d so you only need to store results with a>=b>=c>=d
The count of the last digit will always be 1 or 2 in legal sequences
These tricks should mean the cache only needs to hold about 40 million results.
import random
rc = random.choices([1,2,3,4])
for _ in range(22):
if rc[-1] == 1:
rc = rc + random.choices([2,3,4])
rc = rc + random.choices([1,2,3,4])
if rc[-1] == 2:
rc = rc + random.choices([1,3,4])
rc = rc + random.choices([1,2,3,4])
if rc[-1] == 3:
rc = rc + random.choices([2,1,4])
rc = rc + random.choices([1,2,3,4])
if rc[-1] == 4:
rc = rc + random.choices([2,3,1])
rc = rc + random.choices([1,2,3,4])
print(rc)
Let's say I have a list with 10 numbers:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I would like my program to slice every 3 numbers, for example:
[1,2,3]
[4,5,6]
[7,8,9]
How can I do it?
Grateful
For example, with n = 3,
package main
import "fmt"
func main() {
list := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for a, n := list, 3; len(a) >= n; a = a[n:] {
slice := a[:n]
fmt.Println(slice)
}
}
Output:
[1 2 3]
[4 5 6]
[7 8 9]
you could make a something like this (sorry for pseudo code)
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
while (array){
list = ""
for($i=1;$i -le 3;$i++){
list.add = array[$i]
remove from array the array[$i]
}
your list now here (list)
}
you could ask the first 3 values and after that you remove it
I have the following table
Members
Id, GroupId, Age
1, 1, 12
2, 1, 20
3, 1, 33
4, 2, 12
5, 2, 7
How can I write a LINQ query that will give me a list of the oldest member of each group?
The result should be
Id, GroupId, Age
3, 1, 33
4, 2, 12
from m in members
group m by m.GroupId into g
select g.OrderByDescending(m => m.Age).First()
i need to calculate possible number of outcomes with detail screens.
the detail are: we have 1 textbox in which there has to enter any number from 0 to 7. There are 13 categories of the outcomes but average of all outcomes should be equal to the number entered in the texbox.
for example : textbox : __enter a number from 1 to 7__(if 3)______.
categories 1: 1, 2, 3, 4, 5, 6, 7
categories 2: 1, 2, 3, 4, 5, 6, 7
categories 3: 1, 2, 3, 4, 5, 6, 7
categories 4: 1, 2, 3, 4, 5, 6, 7
categories 5: 1, 2, 3, 4, 5, 6, 7
categories 6: 1, 2, 3, 4, 5, 6, 7
categories 7: 1, 2, 3, 4, 5, 6, 7
categories 8: 1, 2, 3, 4, 5, 6, 7
categories 9: 1, 2, 3, 4, 5, 6, 7
categories 10: 1, 2, 3, 4, 5, 6, 7
categories 11: 1, 2, 3, 4, 5, 6, 7
categories 12: 1, 2, 3, 4, 5, 6, 7
categories 13: 1, 2, 3, 4, 5, 6, 7
the average shud be 3. This is one possibility i need number of possibilities with screens like this.
can any one help me out in this i guess this to be deal with some probability distributions.
As a Haskell list comprehension: (with only 3 parameters, but you get the point)
lists input = [ [a,b,c] | a <- [0..7],b <- [0..7],c <- [0..7], avg([a,b,c]) == input]
then you select any random list from this list of lists