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"
This question already has answers here:
Algorithm: optimal way to rearrange a list from one order to another?
(4 answers)
Closed 4 years ago.
Given two lists, for example:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [2, 4, 6, 7, 0, 1, 3, 5, 8, 9]
I wish to find a series of moves which will transform list a into list b, where each move is an operation:
move(from_index, to_index)
which moves the element at location from_index and places it at location to_index. So if:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
then the operation move(3,1) on the list a will transform a into:
a = [0, 3, 1, 2, 4, 5, 6, 7, 8, 9]
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [2, 4, 6, 7, 0, 1, 3, 5, 8, 9]
move(0, 8)
a = [1, 2, 3, 4, 5, 6, 7, 0, 8, 9]
move(0, 8)
a = [2, 3, 4, 5, 6, 7, 0, 1, 8, 9]
move(1, 8)
a = [2, 4, 5, 6, 7, 0, 1, 3, 8, 9]
move(2, 8)
a = [2, 4, 6, 7, 0, 1, 3, 5, 8, 9]
a==b
Hopefully that's what you're looking for.
Basically, start with the left- most element and move it to where it should be. For example, I took 0 and placed it right after the value that it is supposed to eventually end up behind, which is 7. I continued moving from left to right until all of the elements were in the desired order.
I'd iterate over the second sequence (the sorted list) and swap items in the first. I wrote this pseudo-code in python:
>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b = [2, 4, 6, 7, 0, 1, 3, 5, 8, 9]
>>> def swap(seq, i, j):
... a = seq[i]
... seq[i] = seq[j]
... seq[j] = a
...
>>> for index_in_b, value in enumerate(b):
... index_in_a = a.index(value)
... if index_in_b != index_in_a:
... swap(a, index_in_a, index_in_b)
... print('move {} to {}'.format(index_in_a, index_in_b))
move 0 to 2
move 1 to 4
move 2 to 6
move 3 to 7
move 4 to 6
move 5 to 6
move 6 to 7
In this case I'm moving the items in the first sequence by swapping them.
Update
We can slightly improve the performance in python by removing the move inside swap function and also removing the function call. Here is a performance comparison:
import timeit
s1 = """
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [2, 4, 6, 7, 0, 1, 3, 5, 8, 9]
def swap(seq, i, j):
a = seq[i]
seq[i] = seq[j]
seq[j] = a
for index_in_b, value in enumerate(b):
index_in_a = a.index(value)
if index_in_b != index_in_a:
swap(a, index_in_a, index_in_b)"""
s2 = """
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [2, 4, 6, 7, 0, 1, 3, 5, 8, 9]
for index_in_b, value in enumerate(b):
index_in_a = a.index(value)
if index_in_b != index_in_a:
a[index_in_a], a[index_in_b] = a[index_in_b], a[index_in_a]"""
# on an i7 macbook pro
timeit.timeit(s1)
4.087386846542358
timeit.timeit(s2)
3.5381240844726562
Slightly better, but for sure there are better ways to achieve this.
70, 1 , 1, 6, 5, 8, 5, 9, 4, 10, 8, 40, 58, 2, 0, 6, 91, 45, 66, 10, 66, 6, 42, 30, 25, 20, 16, 11, 19
Using the numbers above, create a program that will display the tree structure once all the numbers are inserted.
example:
--------------------------------70--------------------------------
--------------------1---------------------1-----------------------
------------6-------------5------------8---------5----------------
Im having trouble comprehending how thisi s done
70 is the root node
1 and 1 and the second level node, they both depend of 70
6, 5, 8, 5 are the third level node, 6 and 5 depend of the first 1, 8 and 5 depend of the second 1
then on the fourth level, 9 and 4 depend of 6
etc
Given an array a = {1,2,3,4,5,6,7,8}
We should bring all the odd place elements(1,3,5,7) together and even place elements(2,4,6,8) together while preserving the order.
Input : [1,2,3,4,5,6,7,8].
Output : [1,3,5,7,2,4,6,8].
Update:(Example 2)
Example 2 : [3,54,77,86,45,2,25,100]
Output : [3, 77, 45, 25, 54, 86, 2, 100]
Restrictions: O(N) time complexity and O(1) space complexity.
My approach :
1. partitioning it like in (quicksort partition)
Problem : the order is not preserved. ( 1,7,3,5,4,6,2,8) -O(N) time complex
2. Putting the odd element to the rightful position and shifting all the other elements :
Problem : It comes to O(N) for each element and shifting takes another O(N). So the time complexity becomes O(N^2)
Is there a O(N) time complex and O(1) space complex solution possible?
See if you can generalize either of these permutation solutions based on cycles, noting that sorted indices would be I[] = {0,2,4,6,1,3,5,7}, I[1] = 2, I[2] = 4, I[4] = 1 , end of cycle. I[3] = 6, I[6] = 5, I[5] = 3, end of cycle. The issue here is if n is not known in advance, then even though I[i] can be calculated on the fly (I[i] = (2*i < n) ? 2*i : (2*i-n) | 1; ), the issue is keeping track of which cycles have already been processed, which could require O(n) space.
For 8 elements, it's two cycles, 3 elements each:
0 1 2 3 4 5 6 7
I[] = 0 2 4 6 1 3 5 7
t = a[1] 2
a[1] = a[2] 1 3 3 4 5 6 7 8
a[2] = a[4] 1 3 5 4 5 6 7 8
a[4] = t 1 3 5 4 2 6 7 8
t = a[3] 4
a[3] = a[6] 1 3 5 7 2 6 7 8
a[6] = a[5] 1 3 5 7 2 6 6 8
a[5] = t 1 3 5 7 2 4 6 8
for 12 elements, it's just one cycle of 10 elements
0 1 2 3 4 5 6 7 8 9 10 11
I[] = 0 2 4 6 8 10 1 3 5 7 9 11
t = a[ 1] 2
a[ 1] = a[ 2] 1 3 3 4 5 6 7 8 9 10 11 12
a[ 2] = a[ 4] 1 3 5 4 5 6 7 8 9 10 11 12
a[ 4] = a[ 8] 1 3 5 4 9 6 7 8 9 10 11 12
a[ 8] = a[ 5] 1 3 5 4 9 6 7 8 6 10 11 12
a[ 5] = a[10] 1 3 5 4 9 11 7 8 6 10 11 12
a[10] = a[ 9] 1 3 5 4 9 11 7 8 6 10 10 12
a[ 9] = a[ 7] 1 3 5 4 9 11 7 8 6 8 10 12
a[ 7] = a[ 3] 1 3 5 4 9 11 7 4 6 8 10 12
a[ 3] = a[ 6] 1 3 5 7 9 11 7 4 6 8 10 12
a[ 6] = t 1 3 5 7 9 11 2 4 6 8 10 12
For 27 elements, it's 3 cycles, starting at a[1] (19 elements), a[3] (6 elements), and a[9] (2 elements).
This is a partial answer only.
Here's the executable pseudocode for the first half of the array:
def magic_swap(arr):
mid = len(arr) / 2 + (1 if len(arr) % 2 == 1 else 0)
for i in range(1, mid):
arr[i], arr[i*2] = arr[i*2], arr[i]
The second half is the tricky part... I will update this answer if I ever figure out it.
For people who want to figure this out, here's the results for the first few array sizes:
Note that arrays of size n and n+1, when n is odd, always have the same sequence of swaps in this approach.
[1, 2]
[1, 3, 2]
[1, 3, 2, 4]
[1, 3, 5, 4, 2]
[1, 3, 5, 4, 2, 6]
[1, 3, 5, 7, 2, 6, 4]
[1, 3, 5, 7, 2, 6, 4, 8]
[1, 3, 5, 7, 9, 6, 4, 8, 2]
[1, 3, 5, 7, 9, 6, 4, 8, 2, 10]
[1, 3, 5, 7, 9, 11, 4, 8, 2, 10, 6]
[1, 3, 5, 7, 9, 11, 4, 8, 2, 10, 6, 12]
[1, 3, 5, 7, 9, 11, 13, 8, 2, 10, 6, 12, 4]
[1, 3, 5, 7, 9, 11, 13, 8, 2, 10, 6, 12, 4, 14]
[1, 3, 5, 7, 9, 11, 13, 15, 2, 10, 6, 12, 4, 14, 8]
[1, 3, 5, 7, 9, 11, 13, 15, 2, 10, 6, 12, 4, 14, 8, 16]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 10, 6, 12, 4, 14, 8, 16, 2]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 10, 6, 12, 4, 14, 8, 16, 2, 18]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 6, 12, 4, 14, 8, 16, 2, 18, 10]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 6, 12, 4, 14, 8, 16, 2, 18, 10, 20]
The problem seems rather hard with O(1) and O(n) restrictions.
Best match I can find is an article Stable minimum space partitioning
in linear time, where they propose a solution for slightly more general problem. However, their algorithm is complex and (IMHO) not applicable in practice.
Unless it is a theoretical question, I suggest to relax restrictions to O(logN) and O(NlogN) respectively, and use simple 'stable partitioning' algorithm (updated):
#inplace reverse block [begin,end) in list l
#O(|end-begin|)
def reverse(l, begin, end):
p = begin
q = end - 1
while p < q:
l[p], l[q] = l[q], l[p]
p = p + 1
q = q - 1
#inplace swaps blocks [begin, mid) and [mid, end) and
#returns a new pivot (dividing point)
#O(|end-begin|)
def swap(l, begin, mid, end):
reverse(l, begin, mid)
reverse(l, mid, end)
reverse(l, begin, end)
return (end - (mid - begin))
#recursive partitioning: partition block [begin, end) into
#even and odd blocks, returns pivot (dividing point)
##O(|end-begin|*log|end-begin|)
def partition(l, begin, end):
if end - begin > 1:
mid = (begin + end) / 2
p = partition(l, begin, mid)
q = partition(l, mid, end)
mid = swap(l, p, mid, q)
return mid
return begin if l[begin] % 2 == 0 else begin + 1
def sort(l):
partition(l, 0, len(l))
return l
print sort([1,2,3,4,5,6,7,8])
Update. For an updated question, article is a direct match. So unless there is some trick which abuses the numerical nature of elements, we don't have a simple solution to that problem.
Here is a python program that works. No extra space needed, only one pass through the array.
You don't require the numbers to be sorted or to keep the original order; just put them together.
arr = [1,3,2,4,5,6,3,55,66,77,21,4,5]
iFirst = 0
iLast = len(arr)-1
print arr
while (iFirst < iLast):
while ((arr[iFirst] & 1)==1): # find next even at the front
iFirst += 1
while ((arr[iLast] & 1)==0): # find next odd at the back
iLast -= 1
k = arr[iLast] # exchange them
arr[iLast] = arr[iFirst]
arr[iFirst] = k
iFirst += 1
iLast -= 1
print arr
Here is the output.
[1, 3, 2, 4, 5, 6, 3, 55, 66, 77, 21, 4, 5]
[1, 3, 5, 21, 5, 77, 3, 66, 55, 6, 4, 4, 2]
I have a text data file that looks like below:
Day-Hour, 08188, 0, 08188, 1, (indicating the time is year 2008, julian day 188, between hour0 and hour1)
Receptor, A, (actual data begins)
1, 2, 3, 4,
5, 6, 7, 8,
Receptor, B,
1, 2, 3, 4,
5, 6, 7, 8,
... (continue data for a total of 22 receptors, each receptor has 8 data values)
Day-Hour, 08188, 1, 08188, 2,
Receptor, A,
1, 2, 3, 4,
5, 6, 7, 8,
Receptor, B,
1, 2, 3, 4,
5, 6, 7, 8,
... (continue data for a total of 22 receptors, each receptor has 8 data values, but this is for hours 1 to 2)
...... (continue the same previous pattern for a total of 24 times)
I'd like to reformat it to be like this:
day, time, receptor, data1, data2, data3, ....data8 (header)
08188, 0, A, 1, 2, 3, 4, 5, 6, 7, 8
08188, 0, B, 1, 2, 3, 4, 5, 6, 7, 8
... (repeat the same hour for all 22 receptor sites)
08188, 1, A, 1, 2, 3, 4, 5, 6, 7, 8
08188, 1, B, 1, 2, 3, 4, 5, 6, 7, 8
...(repeat the same hour for all 22 receptor sites)
...
...(repeat the same order 24 times)
I've managed to achieve the format I want through a couple of steps using combinations of awk and sed with something like below, but I feel it's kind of dumb to go through so many steps, and am hoping for experts' help to approach this in a much simpler step. Your inputs are greatly appreciated!
(example steps:)
step1: $ grep -v "Day-Hour" infile.txt > temp1.txt # remove all Day-Hour lines,
# as I know the order of the data
step2: $ sed '/^$/d' temp1.txt > temp2.txt # remove empty lines
step3: $ awk 'ORS=NR%3" ":"\n"' temp2.txt > temp3.txt #concatenate every 3 lines
step4: $ (create a file, e.g. daytime.txt, with 2 fields (day and hour) with following content)
08188, 0,
(repeat 22 times)
08188, 1,
(repeat 22 times)
.... (continue through hour 23)
step5: $ paste daytime.txt temp3.txt > final.txt
This may do the job:
cat file
Day-Hour, 08188, 0, 08188, 1
Receptor, A,
1, 2, 3, 4,
5, 6, 7, 8,
Receptor, B,
11, 12, 13, 14,
15, 16, 17, 18,
Receptor, C,
21, 22, 23, 24,
25, 26, 27, 28,
Day-Hour, 08188, 1, 08188, 2
Receptor, A,
1, 2, 3, 4,
5, 6, 7, 8,
Receptor, B,
1, 2, 3, 4,
5, 6, 7, 8,
awk -v RS= -v OFS=", " -F", *|\n" 'BEGIN {print "day, time, receptor, data1, data2, data3,....data8"} {for (i=7;i<=NF;i+=13) print $2,$3,$i,$(i+2),$(i+3),$(i+4),$(i+5),$(i+7),$(i+8),$(i+9),$(i+10)}' file
day, time, receptor, data1, data2, data3,....data8
08188, 0, A, 1, 2, 3, 4, 5, 6, 7, 8
08188, 0, B, 11, 12, 13, 14, 15, 16, 17, 18
08188, 0, C, 21, 22, 23, 24, 25, 26, 27, 28
08188, 1, A, 1, 2, 3, 4, 5, 6, 7, 8
08188, 1, B, 1, 2, 3, 4, 5, 6, 7, 8
This will print all Receptor, if its 1 or 22.
This will join them up:
sed 's/$/,/;N;N;N;N;N;N;N; s/\n/ /g' foo.txt
into this:
Day-Hour, 08188, 0, 08188, 1, Receptor, A, 1, 2, 3, 4, 5, 6, 7, 8,
Receptor, B, 1, 2, 3, 4, 5, 6, 7, 8, Day-Hour, 08188, 1, 08188, 2,
Receptor, A, 1, 2, 3, 4, 5, 6, 7, 8, Receptor, B, 1, 2, 3, 4, 5, 6, 7,
8,
Then I got lazy in the repackaging:
... | awk '{ $1 = ""; $4 = ""; $5 = ""; print }' | sed -e 's/ \(.*\) Receptor, \(A,.*\)Receptor, \(B, .*\)/\1\2\n\1\3/'
Which producd the desired output on my system.