Deleting middle element out of a given list in ML - ml

I am brand new to learning standard ML. I want to make a function that takes a list/lists of 3 numbers and deletes the middle number and then reverse the order of the two numbers. So if I have a input of (3, 4, 5) then I want to return (5, 3).
This is what I have so far:
fun twiddle [] = []
| twiddle (x::xs) = x::twiddle xs;
I am not sure how to distinguish the middle item of the list and then delete it.

If there are always three numbers, use a pattern matching three elements:
fun twiddle [a,b,c] = [c,a]

Related

Compact way to index from x to y in 2D list

I am doing the tictactoe project from the Cisco NetAkad course : https://www.youtube.com/watch?v=7GDtI9SpGgU
I did the game disregarding the stated project requirements.
I used for the board a normal list: board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
The programm works and and the output is the same as the project asks for.
The project requirements state however specifically to use a 2D list: board = [[1, 2, 3], [4, 5, 6], [7, 8, 9]. As I wanted to practise using 2D lists I rewrote the programm and found it requires more lines and more complex indexing.
My 1st question is: in the function, which checks whether there is a winner, is it possible with a 2D list to just use indexing to check whether there are 3 consecutive "X" or "O" for all directions? If yes, how?
(I don't think writing the massive amount of 'if' combined with many 'and', like in the video, is efficient and using indexing works well with a normal list)
As a beginner my wording might be unclear, so here is the section checking whether "X" has won and below what I expect it to do:
if board[0][0:3].count("X") == 3 or board[1][0:3].count("X") == 3 \
or board[2][0:3].count("X") == 3 or board[0:3][0].count("X") == 3 \
or board[0:3][1].count("X") == 3 or board[0:3][2].count("X") == 3 \
or board[0:3][0:3].count("X") == 3 or board[0:3][3::-1].count("X") == 3:
print("I won: you lost.")
The index [0][0:3], [1][0:3] and [2][0:3] work as expected (rows), it recognises the win.
However [0:3][0] is being read as [0][0:3] when the programm is run. (checking colums doesn't work)
[0:3][0:3] and [0:3][3::-1] obviously doesn't work (diagonal).
2nd question: What better way is there to check for a winner?
Last question: Is there an advantage of using a 2D list over a normal list in this case?
I am thankful in advance for any feedback.
You can do something like below:
for key in ['X', 'O']:
temp = []
count = 0
for row in board:
if row.count(key) == 3:
count = 3
break
if key in row:
temp.append(row.index(key))
if count == 3 or (len(list(set(temp))) == 1 and len(temp) == 3) or temp in ([0,1,2], [2,1,0]):
print("I won: you lost. " + key + " wins")
The idea of the solution is to get the indexes of the positions of 'X' in the inner lists (the usage of indexes justifies the reason to go for a '2D list' [list of lists] per your last question). This is done by looping over the list per 'row' of the tic-tac-toe. We store the indexes in the variable 'temp'.
The first condition checks whether a row has 3 'X's and if yes, it breaks the execution of the for loop saving a count=3. The second condition is the most interesting because it stores the index of 'X' in the row. For example, when you have X in the middle column, at the end of the loop, temp will be equal to:
[2,2,2] if the tic-tac-toe was
O-X-
O-X-O
-X-O
Consequently, if there is a single unique number in the 'temp' list ([1,1,1] unique is 1, [2,2,2] unique is 2 etc), then there is a winner. This is done by:
len(list(set(temp))) # (inside) Get unique values / Make it a list / Measure its length
If the length is 1, then there is a unique position. In addition to that, and to account for the code running while the tic-tac-toe is not entirely filled, we check for len(temp) == 3. Finally, we check for a diagonal match using the 'temp in ([0,1,2], [2,1,0])' part of the condition
The reason why the 'index [0:3][0]' does not work as you expect it to, is because the first slice points to the entire list for which you are taking the value at position 0 which is [1,2,3]. In other words board[0:3] is equal to board
Since there are so few potential states and only 8 winning states, I might just go directly with evaluating them all:
gameboard = [
["x","-","-"],
["x","-","-"],
["x","-","-"]
]
possilbe_winning_states = [
[(0,0), (0,1), (0,2)],
[(1,0), (1,1), (1,2)],
[(2,0), (2,1), (2,2)],
[(0,0), (1,0), (2,0)],
[(0,1), (1,1), (2,1)],
[(0,2), (1,2), (2,2)],
[(0,0), (1,1), (2,2)],
[(0,2), (1,1), (2,0)]
]
for possilbe_winning_state in possilbe_winning_states:
squares = [gameboard[square[0]][square[1]] for square in possilbe_winning_state]
if squares.count("x") == 3:
print("X Win")
break
elif squares.count("o") == 3:
print("O Win")
break
else:
print("no winner yet")

How to create unique random integer?

is there any posible way to create unique random integer. I know how to make Array or List with unique numbers, but fact is that I need each time different number cause I am creating something like exam, and I am taking values with different id-s from db . If I take duplicate number I would make two same questions on exam.
If there is no way to do it, what do you suggest? how to handle problem. I need to generate different id each time from db.
Thanks in advance.
To create a set of N unique random number from set S, first create a boolean array of size |S| (cardinality of a set, how many elements it contains). Now, each time you generate a random number, check the array to make sure the index of that number is false and set it to true, else pick a different number. Each random number that you generate that had a false index can be added to another array of final numbers.
If I can restate your question, I think you're looking for "How do I randomly pick n numbers out of m available numbers?"
In other words, if you have [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as available numbers and you want to pick 4, one possible result would be [8, 3, 5, 1].
There are a few ways to do this. One of the simplest is to put the initial list in random order and then take the top n elements.
For example, in Python:
>>> available = range(10)
>>> random.shuffle(available)
>>> available[:4]
[5, 8, 6, 9]
This algorithm is a little bit wasteful, because it randomizes the entire list when you don't really need to.
An improvement would be to, one element at a time, swap that element with a random position after it. This is known as the Fisher-Yates shuffle. It looks like this in pseudo-code:
-- To shuffle an array a of n elements (indices 0..n-1):
for i from 0 to nāˆ’2 do
j ā† random integer such that i ā‰¤ j < n
exchange a[i] and a[j]
But instead of going through the whole list, only go n deep, where n is the number of items you need to pick.
Here's a Python implementation:
import random
def sample(items, how_many):
# copy the list
items = list(items)
# just do the first how_many items
for i in range(how_many):
random_index = random.randrange(i, len(items))
# swap the items
items[i], items[random_index] = items[random_index], items[i]
# return the first how_many
return items[:how_many]
print(sample(range(10), 4))
Many languages/libraries have a built-in way to do this. For example, in Python, the built-in random.sample is the equivalent of my code above:
>>> random.sample(range(10), 4)
[1, 5, 0, 4]
In SQL you can try something like this. The code below will give you 14 unique numbers from 0 to 13 and store it in a temp table and you can do whatever you what with it. tested in sql-server 2008
declare #randNumbers table (number int)
declare #rand int, #howMany int
set #howMany = 14
set #rand = Ceiling(ABS(CHECKSUM(NewId())) % 25)
while ((select COUNT(*) from #randNumbers)<10)
begin
set #rand = Ceiling(ABS(CHECKSUM(NewId())) % #howMany)
BEGIN
IF NOT EXISTS (select * from #randNumbers
WHERE number = #rand)
BEGIN
insert into #randNumbers
values(#rand)
END
END
end
select * from #randNumbers
You can create a sequence in your db and use it to get unique non duplicate auto incremented number... And if you need random number, say something between 0000 and 9999 (just an example), then
1. Create a method that generates this random number
2. Use an array to store this used number or store in db
3. Next time you generate another number, check if you have already used the number.
4. Add this whole code in a while loop so that until you don't get a number which is free it will keep generating new ones to check.

Script to calculate the product of numbers in all possible combinations

I have a db of numbers (percentages) which I want to calculate the product for each of the possible combinations of all the numbers and their difference from a 100%.
So for example, for the following numbers:
0.3, 0.4, 0.6, 0.7
I want to calculate the following:
(1-0.3)*(1-0.4)*(1-0.6)*(1-0.7)
0.3*0.4*0.6*0.7
0.3*(1-0.4)*(1-0.6)*(1-0.7)
(1-0.3)*(1-0.4)*(1-0.6)*0.7
(1-0.3)*0.4*(1-0.6)*(1-0.7)
(1-0.3)*(1-0.4)*0.6*(1-0.7)
0.3*(1-0.4)*(1-0.6)*0.7
0.3*(1-0.4)*0.6*(1-0.7)
(1-0.3)*(1-0.4)*0.6*0.7
(1-0.3)*0.4*(1-0.6)*0.7
(1-0.3)*0.4*0.6*(1-0.7)
0.3*0.4*(1-0.6)*(1-0.7)
(1-0.3)*0.4*0.6*0.7
0.3*(1-0.4)*0.6*0.7
0.3*0.4*(1-0.6)*0.7
0.3*0.4*0.6*(1-0.7)
I want to be able to build this for any n numbers (here I gave an example for 4 numbers, but there can be hundreds and thousands of these). How is it called? Is there a command for them? Is there a known script somewhere?
In the end I will need to sum them all up. And use them individually as well.
I do not think there is a pre-defined command for this in any language, but most languages will allow you to write a recursive function for this. For example, in Haskell you could use:
calculate [] = [[]]
calculate (x:xs) = let rec = calculate xs
pos = map (x:) rec
neg = map ((1 - x):) rec
in pos ++ neg
You can try this out here and run your example with the line:
main = print (calculate [0.3, 0.4, 0.6, 0.7])
Note that this calculate function takes a list of percentages as input and returns a list of lists, each of which represents a line in your desired result. This result can then be used to calculate your intermediate and final result.
The function works as follows. If your input is an empty list, return a list with an empty list. If the input has elements, separate the first element (x) from the remainder of the list (xs) and calculate the result on the remainder of the list. The result of this is a list with lists of percentages which is stored in rec.
To calculate the result value, prepend x to each list in rec (stored in pos) and prepend 1-x to each list in rec (stored in neg). As the result we return one list which is the concatenation of pos and neg.

Generating also non-unique (duplicated) permutations

I've written a basic permutation program in C.
The user types a number, and it prints all the permutations of that number.
Basically, this is how it works (the main algorithm is the one used to find the next higher permutation):
int currentPerm = toAscending(num);
int lastPerm = toDescending(num);
int counter = 1;
printf("%d", currentPerm);
while (currentPerm != lastPerm)
{
counter++;
currentPerm = nextHigherPerm(currentPerm);
printf("%d", currentPerm);
}
However, when the number input includes repeated digits - duplicates - some permutations are not being generated, since they're duplicates. The counter shows a different number than it's supposed to - Instead of showing the factorial of the number of digits in the number, it shows a smaller number, of only unique permutations.
For example:
num = 1234567
counter = 5040 (!7 - all unique)
num = 1123456
counter = 2520
num = 1112345
counter = 840
I want to it to treat repeated/duplicated digits as if they were different - I don't want to generate only unique permutations - but rather generate all the permutations, regardless of whether they're repeated and duplicates of others.
Uhm... why not just calculate the factorial of the length of the input string then? ;)
I want to it to treat repeated/duplicated digits as if they were
different - I don't want to calculate only the number of unique
permutations.
If the only information that nextHigherPerm() uses is the number that's passed in, you're out of luck. Consider nextHigherPerm(122). How can the function know how many versions of 122 it has already seen? Should nextHigherPerm(122) return 122 or 212? There's no way to know unless you keep track of the current state of the generator separately.
When you have 3 letters for example ABC, you can make: ABC, ACB, BAC, BCA, CAB, CBA, 6 combinations (6!). If 2 of those letters repeat like AAB, you can make: AAB, ABA, BAA, IT IS NOT 3! so What is it? From where does it comes from? The real way to calculate it when a digit or letter is repeated is with combinations -> ( n k ) = n! / ( n! * ( n! - k! ) )
Let's make another illustrative example: AAAB, then the possible combinations are AAAB, AABA, ABAA, BAAA only four combinations, and if you calcualte them by the formula 4C3 = 4.
How is the correct procedure to generate all these lists:
Store the digits in an array. Example ABCD.
Set the 0 element of the array as the pivot element, and exclude it from the temp array. A {BCD}
Then as you want all the combinations (Even the repeated), move the elements of the temporal array to the right or left (However you like) until you reach the n element.
A{BCD}------------A{CDB}------------A{DBC}
Do the second step again but with the temp array.
A{B{CD}}------------A{C{DB}}------------A{D{BC}}
Do the third step again but inside the second temp array.
A{B{CD}}------------A{C{DB}}------------A{D{BC}}
A{B{DC}}------------A{C{BD}}------------A{D{CB}}
Go to the first array and move the array, BCDA, set B as pivot, and do this until you find all combinations.
Why not convert it to a string then treat your program like an anagram generator?

Algorithm to find "most common elements" in different arrays

I have for example 5 arrays with some inserted elements (numbers):
1,4,8,10
1,2,3,4,11,15
2,4,20,21
2,30
I need to find most common elements in those arrays and every element should go all the way till the end (see example below). In this example that would be the bold combination (or the same one but with "30" on the end, it's the "same") because it contains the smallest number of different elements (only two, 4 and 2/30).
This combination (see below) isn't good because if I have for ex. "4" it must "go" till it ends (next array mustn't contain "4" at all). So combination must go all the way till the end.
1,4,8,10
1,2,3,4,11,15
2,4,20,21
2,30
EDIT2: OR
1,4,8,10
1,2,3,4,11,15
2,4,20,21
2,30
OR anything else is NOT good.
Is there some algorithm to speed this thing up (if I have thousands of arrays with hundreds of elements in each one)?
To make it clear - solution must contain lowest number of different elements and the groups (of the same numbers) must be grouped from first - larger ones to the last - smallest ones. So in upper example 4,4,4,2 is better then 4,2,2,2 because in first example group of 4's is larger than group of 2's.
EDIT: To be more specific. Solution must contain the smallest number of different elements and those elements must be grouped from first to last. So if I have three arrrays like
1,2,3
1,4,5
4,5,6
Solution is 1,1,4 or 1,1,5 or 1,1,6 NOT 2,5,5 because 1's have larger group (two of them) than 2's (only one).
Thanks.
EDIT3: I can't be more specific :(
EDIT4: #spintheblack 1,1,1,2,4 is the correct solution because number used first time (let's say at position 1) can't be used later (except it's in the SAME group of 1's). I would say that grouping has the "priority"? Also, I didn't mention it (sorry about that) but the numbers in arrays are NOT sorted in any way, I typed it that way in this post because it was easier for me to follow.
Here is the approach you want to take, if arrays is an array that contains each individual array.
Starting at i = 0
current = arrays[i]
Loop i from i+1 to len(arrays)-1
new = current & arrays[i] (set intersection, finds common elements)
If there are any elements in new, do step 6, otherwise skip to 7
current = new, return to step 3 (continue loop)
print or yield an element from current, current = arrays[i], return to step 3 (continue loop)
Here is a Python implementation:
def mce(arrays):
count = 1
current = set(arrays[0])
for i in range(1, len(arrays)):
new = current & set(arrays[i])
if new:
count += 1
current = new
else:
print " ".join([str(current.pop())] * count),
count = 1
current = set(arrays[i])
print " ".join([str(current.pop())] * count)
>>> mce([[1, 4, 8, 10], [1, 2, 3, 4, 11, 15], [2, 4, 20, 21], [2, 30]])
4 4 4 2
If all are number lists, and are all sorted, then,
Convert to array of bitmaps.
Keep 'AND'ing the bitmaps till you hit zero. The position of the 1 in the previous value indicates the first element.
Restart step 2 from the next element
This has now turned into a graphing problem with a twist.
The problem is a directed acyclic graph of connections between stops, and the goal is to minimize the number of lines switches when riding on a train/tram.
ie. this list of sets:
1,4,8,10 <-- stop A
1,2,3,4,11,15 <-- stop B
2,4,20,21 <-- stop C
2,30 <-- stop D, destination
He needs to pick lines that are available at his exit stop, and his arrival stop, so for instance, he can't pick 10 from stop A, because 10 does not go to stop B.
So, this is the set of available lines and the stops they stop on:
A B C D
line 1 -----X-----X-----------------
line 2 -----------X-----X-----X-----
line 3 -----------X-----------------
line 4 -----X-----X-----X-----------
line 8 -----X-----------------------
line 10 -----X-----------------------
line 11 -----------X-----------------
line 15 -----------X-----------------
line 20 -----------------X-----------
line 21 -----------------X-----------
line 30 -----------------------X-----
If we consider that a line under consideration must go between at least 2 consecutive stops, let me highlight the possible choices of lines with equal signs:
A B C D
line 1 -----X=====X-----------------
line 2 -----------X=====X=====X-----
line 3 -----------X-----------------
line 4 -----X=====X=====X-----------
line 8 -----X-----------------------
line 10 -----X-----------------------
line 11 -----------X-----------------
line 15 -----------X-----------------
line 20 -----------------X-----------
line 21 -----------------X-----------
line 30 -----------------------X-----
He then needs to pick a way that transports him from A to D, with the minimal number of line switches.
Since he explained that he wants the longest rides first, the following sequence seems the best solution:
take line 4 from stop A to stop C, then switch to line 2 from C to D
Code example:
stops = [
[1, 4, 8, 10],
[1,2,3,4,11,15],
[2,4,20,21],
[2,30],
]
def calculate_possible_exit_lines(stops):
"""
only return lines that are available at both exit
and arrival stops, discard the rest.
"""
result = []
for index in range(0, len(stops) - 1):
lines = []
for value in stops[index]:
if value in stops[index + 1]:
lines.append(value)
result.append(lines)
return result
def all_combinations(lines):
"""
produce all combinations which travel from one end
of the journey to the other, across available lines.
"""
if not lines:
yield []
else:
for line in lines[0]:
for rest_combination in all_combinations(lines[1:]):
yield [line] + rest_combination
def reduce(combination):
"""
reduce a combination by returning the number of
times each value appear consecutively, ie.
[1,1,4,4,3] would return [2,2,1] since
the 1's appear twice, the 4's appear twice, and
the 3 only appear once.
"""
result = []
while combination:
count = 1
value = combination[0]
combination = combination[1:]
while combination and combination[0] == value:
combination = combination[1:]
count += 1
result.append(count)
return tuple(result)
def calculate_best_choice(lines):
"""
find the best choice by reducing each available
combination down to the number of stops you can
sit on a single line before having to switch,
and then picking the one that has the most stops
first, and then so on.
"""
available = []
for combination in all_combinations(lines):
count_stops = reduce(combination)
available.append((count_stops, combination))
available = [k for k in reversed(sorted(available))]
return available[0][1]
possible_lines = calculate_possible_exit_lines(stops)
print("possible lines: %s" % (str(possible_lines), ))
best_choice = calculate_best_choice(possible_lines)
print("best choice: %s" % (str(best_choice), ))
This code prints:
possible lines: [[1, 4], [2, 4], [2]]
best choice: [4, 4, 2]
Since, as I said, I list lines between stops, and the above solution can either count as lines you have to exit from each stop or lines you have to arrive on into the next stop.
So the route is:
Hop onto line 4 at stop A and ride on that to stop B, then to stop C
Hop onto line 2 at stop C and ride on that to stop D
There are probably edge-cases here that the above code doesn't work for.
However, I'm not bothering more with this question. The OP has demonstrated a complete incapability in communicating his question in a clear and concise manner, and I fear that any corrections to the above text and/or code to accommodate the latest comments will only provoke more comments, which leads to yet another version of the question, and so on ad infinitum. The OP has gone to extraordinary lengths to avoid answering direct questions or to explain the problem.
I am assuming that "distinct elements" do not have to actually be distinct, they can repeat in the final solution. That is if presented with [1], [2], [1] that the obvious answer [1, 2, 1] is allowed. But we'd count this as having 3 distinct elements.
If so, then here is a Python solution:
def find_best_run (first_array, *argv):
# initialize data structures.
this_array_best_run = {}
for x in first_array:
this_array_best_run[x] = (1, (1,), (x,))
for this_array in argv:
# find the best runs ending at each value in this_array
last_array_best_run = this_array_best_run
this_array_best_run = {}
for x in this_array:
for (y, pattern) in last_array_best_run.iteritems():
(distinct_count, lengths, elements) = pattern
if x == y:
lengths = tuple(lengths[:-1] + (lengths[-1] + 1,))
else :
distinct_count += 1
lengths = tuple(lengths + (1,))
elements = tuple(elements + (x,))
if x not in this_array_best_run:
this_array_best_run[x] = (distinct_count, lengths, elements)
else:
(prev_count, prev_lengths, prev_elements) = this_array_best_run[x]
if distinct_count < prev_count or prev_lengths < lengths:
this_array_best_run[x] = (distinct_count, lengths, elements)
# find the best overall run
best_count = len(argv) + 10 # Needs to be bigger than any possible answer.
for (distinct_count, lengths, elements) in this_array_best_run.itervalues():
if distinct_count < best_count:
best_count = distinct_count
best_lengths = lengths
best_elements = elements
elif distinct_count == best_count and best_lengths < lengths:
best_count = distinct_count
best_lengths = lengths
best_elements = elements
# convert it into a more normal representation.
answer = []
for (length, element) in zip(best_lengths, elements):
answer.extend([element] * length)
return answer
# example
print find_best_run(
[1,4,8,10],
[1,2,3,4,11,15],
[2,4,20,21],
[2,30]) # prints [4, 4, 4, 30]
Here is an explanation. The ...this_run dictionaries have keys which are elements in the current array, and they have values which are tuples (distinct_count, lengths, elements). We are trying to minimize distinct_count, then maximize lengths (lengths is a tuple, so this will prefer the element with the largest value in the first spot) and are tracking elements for the end. At each step I construct all possible runs which are a combination of a run up to the previous array with this element next in sequence, and find which ones are best to the current. When I get to the end I pick the best possible overall run, then turn it into a conventional representation and return it.
If you have N arrays of length M, this should take O(N*M*M) time to run.
I'm going to take a crack here based on the comments, please feel free to comment further to clarify.
We have N arrays and we are trying to find the 'most common' value over all arrays when one value is picked from each array. There are several constraints 1) We want the smallest number of distinct values 2) The most common is the maximal grouping of similar letters (changing from above for clarity). Thus, 4 t's and 1 p beats 3 x's 2 y's
I don't think either problem can be solved greedily - here's a counterexample [[1,4],[1,2],[1,2],[2],[3,4]] - a greedy algorithm would pick [1,1,1,2,4] (3 distinct numbers) [4,2,2,2,4] (two distinct numbers)
This looks like a bipartite matching problem, but I'm still coming up with the formulation..
EDIT : ignore; This is a different problem, but if anyone can figure it out, I'd be really interested
EDIT 2 : For anyone that's interested, the problem that I misinterpreted can be formulated as an instance of the Hitting Set problem, see http://en.wikipedia.org/wiki/Vertex_cover#Hitting_set_and_set_cover. Basically the left hand side of the bipartite graph would be the arrays and the right hand side would be the numbers, edges would be drawn between arrays that contain each number. Unfortunately, this is NP complete, but the greedy solutions described above are essentially the best approximation.

Resources