I think case of is quite straight forward, as i come from more imperative languages.
Nevertheless, i have encountered a Kata where one of the solutions by another user, confuses me about the use of case and Data.List (sort)
import Data.List (sort)
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c =
case sort [a,b,c] of
[min, middle, max] -> (min + middle) > max
By definition, 3 segments can make a triangle if the condition a + b > c is met for the 3 permutations of [a,b,c] so, something more straight forward (my answer) would be:
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c = a + b > c && b + c > a && a + c > b
My question is, in the case above, how is the case of testing that condition for the 3 combinations?
Imagine that a b and c are ordered from small to large, then the algorithm tests that a + b > c, which is what the first implementation checks.
If we know that a < b < c, and a + b > c holds, then we know that a + c > b holds. Indeed: a + c > a + b > c > b, hence a + c > b holds because a + b > c holds. Furthermore b + c > a + b > c > a holds, and thus b + c > a holds as well.
This thus means that checking if it holds for a known minimum, maximum and value in between, the two other equations are implied.
What the case … of does here is sorting the list [a, b, c] and unpacking the sorted list in min, middle and max, it is thus a tool that is used to assign the smallest value to min, the largest value to max and the remaining value to middle. A where … or let … in … is probably more elegant, for example:
isTriangle :: Int -> Int -> Int -> Bool
isTriangle a b c = (min + middle) > max
where [min, middle, max] = sort [a, b, c]
I need to write a function that makes the same job as [a..b] by using the : operator and guards.
is it possible to do it? where should I begin?
list a b
| a < b = print[a..b]
| otherwise = print[a,a-1..b]
You can try deriving it from the laws it must follow, i.e.
list a b | a > b = []
list a b | a <= b = [a..b]
= a : [(a+1)..b]
But then we can read the last equation right to left to get
[(a+1)..b] = list (a+1) b
and substituting it back into the last law gives us the definition that we needed.
update: so looks like what you really wanted is to count up or down depending on the relation between a and b. This just needs some tweaking:
list a b | a == b = [a]
list a b | a < b = [a..b]
= a : [(a+1)..b]
= a : list (a+1) b
list a b | a > b = [a,a-1..b]
= a : [a-1,a-2..b]
= a : list (a-1) b
This will perform some redundant checks while counting. These can be avoided by defining two specialized internal functions for the counting up or down, and using those after the initial checks.
Is it better to compare with the parent function or within the same function? #Will Ness
list a b| a < b = greaterB a b
list a b| a >= b = greaterA a b
greaterB a b
| a > b = []
| a <= b = a:greaterB(a+1) b
greaterA a b
| a >= b = a:greaterA(a-1) b
| a < b = []
I have a dataframe column that looks like this (roughly 200 rows):
col1
a
b
c
d
e
f
I want to create a new dataframe with one column and 15 sets of 3 random combinations of the items in the pandas column. for example:
new_df
combinations:
(a,b,c)
(a,c,d)
(a,d,c)
(b,a,d)
(d,a,c)
(a,d,f)
(e,a,f)
(a,f,e)
(b,e,f)
(f,b,e)
(c,b,e)
(b,e,a)
(a,e,f)
(e,f,a)
Currently the code I have creates a combination of every possible combination and runs out of memory when I try to append the results to another dataframe:
import pandas as pd
from itertools import permutations
df = pd.read_csv('')
combo = df['col1'].tolist()
perm = permutations(combo,3)
combinations = pd.DataFrame(columns=['combinations'])
list_ = []
for i in list(perm):
combinations['combinations'] = i
list_.append(i)
How do I stop the sets of random combinations to stop at any X number of set or in this case 15 combinations of 3?
The reason your code runs out of memory is specifically because of the part where you call list(perm). doing this will generate EVERY permutation possible. So when you do
for i in list(perm):
...
You're telling python to create a list of all permutations, then try to iterate over that list. Instead, if you iterate over the generator that calling permutations creates (e.g. for i in perm: instead of for i in list(perm):), you can simply iterate over each permutation without storing them all into memory at once. So if you break your for loop after it loops 15 times, you can achieve your desired result.
However, since we're using itertools, we can vastly simplify that logic using islice to do the work of getting the first 15 without explicitly writing a for-loop and breaking at the 15th iteration:
import pandas as pd
from itertools import permutations, islice
# df = pd.read_csv('')
# combo = df['col1'].tolist()
combo = list("abcefg")
perm_generator = permutations(combo,3)
# get first 15 permutations without running the generator
first_15_perms = islice(perm_generator, 15)
# Store the first 15 permutations into a Series object
series_perms = pd.Series(list(first_15_perms), name="permutations")
print(series_perms)
0 (a, b, c)
1 (a, b, e)
2 (a, b, f)
3 (a, b, g)
4 (a, c, b)
5 (a, c, e)
6 (a, c, f)
7 (a, c, g)
8 (a, e, b)
9 (a, e, c)
10 (a, e, f)
11 (a, e, g)
12 (a, f, b)
13 (a, f, c)
14 (a, f, e)
Name: permutations, dtype: object
If you want this as a single column in a DataFrame you can use the to_frame() method:
df_perms = series_perms.to_frame()
print(df_perms)
permutations
0 (a, b, c)
1 (a, b, e)
2 (a, b, f)
3 (a, b, g)
4 (a, c, b)
5 (a, c, e)
6 (a, c, f)
7 (a, c, g)
8 (a, e, b)
9 (a, e, c)
10 (a, e, f)
11 (a, e, g)
12 (a, f, b)
13 (a, f, c)
14 (a, f, e)
While not quite as elegant as the previous answers, If you truly want to create a random sampling of values, not just the first you could also do something along the lines of the following:
def newFrame(df: pd.DataFrame, srccol: int, cmbs: int, rows: int) -> pd.DataFrame:
il = df[srccol].values.tolist()
nw_df = pd.DataFrame()
data = []
for r in range(rows):
rd =[]
for ri in range(cmbs):
rd.append(rnd.choice(il))
data.append(tuple(rd))
nw_df['Combinations'] = data
return nw_df
Which when passed a a df as shown in your example in the form of:
new_df = newFrame(df, 0, 3, 15)
Produces:
Combinations
0 (a, f, e)
1 (a, d, f)
2 (b, c, d)
3 (a, a, d)
4 (f, b, c)
5 (e, b, b)
6 (e, e, d)
7 (c, f, f)
8 (f, e, b)
9 (d, c, e)
I was taught a different way to calculate exponents using mod and recursion, but I don't fully understand it. The method is: To do b^e, we can break it down like so:
q = e div 2
r = e mod 2
then e = 2q+r, and r could be 0 or 1.
If r=0:
b^e = (b^q)^2
If r=1:
b^e = (b^q)^2 * b
base case: b^0 = 1.
For example: 2^2, b=2, e=2.
q = 2/2 = 1
r = 2mod2 = 0
r=0, therefore 2^2 = 2^1^2
I am trying to code this.
pow :: Integer -> Integer -> Integer
pow b e
| e == 0 = 1
| r == 0 = pow (pow b q) 2
| r == 1 = b * pow (pow b q) 2
where
(q, r) = divMod e 2
But the code does not end any time when e!=0, for example, pow (-2) 4 or pow 1 1 goes on forever. Any idea why?
If you try evaluating pow b 2 by hand you'll quickly see why. Since divMod 2 2 = (1, 0), we expand from pow b 2 to pow (pow b 1) 2. Note that this is also of the form pow b' 2, with b' = pow b 1. So we just get an infinite chain:
pow b 2
=
pow (pow b 1) 2
=
pow (pow (pow b 1) 1) 2
=
pow (pow (pow (pow b 1) 1) 1) 2
=
...
There's a couple ways to solve it. You could add a base case for e == 2, or instead of recursively calling pow twice you could just do the multiplication yourself (as in replacing pow foo 2 with foo * foo in your existing code).
You also need to provide a base case for when e is 2:
pow b 2 = b * b
Without this, your recursion doesn't end, because it becomes pow (pow b 1) 2 and you don't get anywhere.
As mentioned in the previous answers, your code almost works, and it is just a matter of allowing the recursion to stop.
See the code below for a possible fix. The argument of the recursive call is at most half the current argument, hence the recursion will have to stop.
On a side note, this algorithm is more than 2,000 years old, and originated in ancient India. Please treat it with all due respect :-)
https://mathoverflow.net/questions/107708/origin-of-square-and-multiply-algorithm
pow :: Integer -> Integer -> Integer
pow b e
| e == 0 = 1
| r == 0 = let bpq = pow b q in bpq*bpq
| r == 1 = let bpq = pow b q in bpq*bpq*b
where
(q, r) = divMod e 2
main = do
let b = 3 :: Integer
let e = 7 :: Integer
let x = b^e
putStrLn ("b^e = " ++ show x)
let y = pow b e
putStrLn ("pow b e = " ++ show y)
f0 :: Int -> Int -> Int -> Int
f0 a b c = x a b - x a c - x b c
where x b a = a + b
Can someone explain me how the functions knows what to do when it gets to the...
where x b a = a + b
... statement? Does it just translate to something like this?
f0 a b c = (a + b) a b - (a + b) a c - (a + b) b c
[...] or is it just that the "x" is just another functions which takes two variables and add them [...]
Exactly. x b a = a + b is a function definition (that happens to have local scope). f0 0 0 1 = x 0 0 - x 0 1 - x 0 1. – duplode
In some other pseudo language this will look like this.
int function fo(int a, int b, int c){
int function x(int a, int b){
return a + b;
}
return x(a,b) - x(a,c) - x(b,c)
}
The way you have put it as a question,
f0 a b c = (a + b) a b - (a + b) a c - (a + b) b c
it looks like inline substitution like C macros. It is not simple code substitution. It is more like inline function. X is a function which gets called.