I'm trying to write a function in Standard ML using case of but I end up with code that screams for a bunch of if / else's. Is this just a poor candidate for using case of or is there a better way of setting this up so I'm not constantly mapping booleans to booleans?
Here's my code:
fun isLeapYear(y) =
case (y mod 400 = 0) of
true => true |
false => (case ((y mod 100 = 0)) of
true => false |
false => (case (y mod 4 = 0) of
true => true |
false => false));
Thanks for the help,
bclayman
If you don't care about a few extra instructions:
fun isLeapYear(y) = case (y mod 400, y mod 100, y mod 4) of
(0, _, _) => true
| (_, 0, _) => false
| (_, _, 0) => true
| (_, _, _) => false
Firstly, case X of true => E1 | false => E2" directly corresponds to if X then E1 else E2, which I personally would prefer. (After all, if ... then ... else ... is kind of a specialized case construct, which only works on booleans, right?) Turning it into that gives us:
fun isLeapYear(y) =
if y mod 400 = 0 then true
else if y mod 100 = 0 then false
else if y mod 4 = 0 then true
else false
Which brings me to the second point: You can always rewrite an if B then E1 else E2, where one of the Es is true or false, using the following table:
(Pardon the Danish headings, it's taken from the book "IP-2: Supplerende noter i Introduktion til programmering", which we use for teaching SML at University of Copenhagen.)
Anyhow, rewriting using this, we get:
fun isLeapYear(y) =
if y mod 400 = 0 then true
else if y mod 100 = 0 then false
else if y mod 4 = 0 then true
else false
becomes
fun isLeapYear(y) =
if y mod 400 = 0 then true
else if y mod 100 = 0 then false
else y mod 4 = 0
becomes
fun isLeapYear(y) =
if y mod 400 = 0 then true
else not (y mod 100 = 0) andalso y mod 4 = 0
becomes
fun isLeapYear(y) = y mod 400 = 0 orelse (not (y mod 100 = 0) andalso y mod 4 = 0)
Finally we can turn the not (y mod 100 = 0) into y mod 100 <> 0, giving:
fun isLeapYear(y) = y mod 400 = 0 orelse (y mod 100 <> 0 andalso y mod 4 = 0)
In general whenever you see
case p of
true => true
| false => q
(or equivalently if p then true else q) you should write
p orelse q
Likewise
case p of
false => false
true => q
is just p andalso q
Finally
case p of
true => true
false => false
is just p.
So your example is better written as
y mod 400 = 0
orelse (y mod 100 <> 0
andalso y mod 4 = 0)
Related
Im currently working on a project about the multiple encryption method! I am having a lot of trouble with RSA. I have a code that encrypt, give the public and the private key. Now I need to let someone write the private key and the encrypted text, and make the program decrypt it. I tried many times, ando got so many different erros that I deleted the decrypt function to do it over from start. Could anyone shine some ligth upon me? How to do, what should I do... Any help, really.
This is the code:
import random
def totient(number):
if(prime(number)):
return number-1
else:
return False
def prime(n):
if (n <= 1):
return False
if (n <= 3):
return True
if (n%2 == 0 or n%3 == 0):
return False
i = 5
while(i * i <= n):
if (n%i == 0 or n%(i+2) == 0):
return False
i+=6
return True
def generate_E(num):
def mdc(n1,n2):
rest = 1
while(n2 != 0):
rest = n1%n2
n1 = n2
n2 = rest
return n1
while True:
e = random.randrange(2,num)
if(mdc(num,e) == 1):
return e
def generate_prime():
while True:
x=random.randrange(1,100)
if(prime(x)==True):
return x
def mod(a,b):
if(a<b):
return a
else:
c=a%b
return c
def cipher(words,e,n):
tam = len(words)
i = 0
lista = []
while(i < tam):
letter = words[i]
k = ord(letter)
k = k**e
d = mod(k,n)
lista.append(d)
i += 1
return lista
def calculate_private_key(toti,e):
d = 0
while(mod(d*e,toti)!=1):
d += 1
return d
## MAIN
if __name__=='__main__':
text = input("Insert message: ")
p = generate_prime() # generates random P
q = generate_prime() # generates random Q
n = p*q # compute N
y = totient(p) # compute the totient of P
x = totient(q) # compute the totient of Q
totient_de_N = x*y # compute the totient of N
e = generate_E(totient_de_N) # generate E
public_key = (n, e)
print('Your public key:', public_key)
text_cipher = cipher(text,e,n)
print('Your encrypted message:', text_cipher)
d = calculate_private_key(totient_de_N,e)
print('Your private key is:', d)
i've been trying to turn the recurrence formula underneath into a pseudocode that uses memoization, however currently all i know is my below attempt is incorrect, is anyone able to point me in the right direction?
My recurrence formula:
N(C,i) =
1 if C = 0
0 if i=0 or C<0}
N(C-p_i, i-1) + N(C, i-1) otherwise
My current attempt:
MEM-N(C, i, r)
if r[i] >= 0 then
return r[i]
if i = 0 and r[i] >= 0 or C < 0 and r[i] >= 0 then
return 0
else if C = 0 and r[i] >= 0 then
return 1
else
q = -$\infty$
q = MEM-N(C - $p_i$, i-1) + MEM-N(C,i - x, r)
r[i] = q
return q
Following on from the comments:
MEM-N(C, i, r)
if C = 0 then
return 1
else if i = 0 or C < 0 then
return 0
else if r[i] >= 0 then
return r[i] # move here
else
q = MEM-N(C - p_i, i - 1, r) + MEM-N(C, i - 1, r) # fix
r[i] = q
return q
the following error occurs. I tried to change the n .... but not working
"LoadError: BoundsError: attempt to access 9-element Array{Float64,1}:"
function bernstein_vandermonde( n )
if n == 1
v = ones(1, 1);
return v
end
v = zeros( n, n );
x = linspace( 0, 1, n );
for i = 1:n
println("entra no loop")
v[i,1:n] = bernstein_poly_01(n - 1, x[i])
end
return v
end
function bernstein_poly_01( n, x )
bern = ones(n)
if n == 0
bern[1] = 1
elseif 0 < n
bern[1] = 1 -x
bern[2] = x
for i = 2:n
bern[i+1] = x*bern[i];
for j = i-1:-1: 1
bern[j+1] = x*bern[j] + (1 - x)*bern[j+1]
end
bern[1] = (1 - x)*bern[1]
end
end
return bern
end
I can not solve :(
I tried to implement an algorithm to calculate power towers
modulo m. Below the procedure tower should calculate
2^3^...^14^15 (mod m) and tower2 should calculate
15^14^...^3^2 (mod m). But for m = 163 , tower2
produces a wrong answer. I found out that a immediate
result is 0 and the procedure does not get this.
Can anyone fix the error ?
The procedure powmod is implemented and works perfectly :
powmod(basis,exponent,modul)={if(exponent==0,hilf=1);if(exponent>0,bin=binary(exponent);hilf=basis;hilf=hilf-truncate(hilf/modul)*modul;for(stelle=2,length(bin),hilf=hilf^2;if(bin[stelle]==1,hilf=hilf*basis);hilf=hilf-truncate(hilf/modul)*modul));hilf}
? tower
%19 = (p,q,r)->if(q==0,hilf=1);if(q==1,hilf=p);if(q==2,hilf=powmod(p,p,r));if(q>
2,x=[];for(j=1,q,x=concat(x,r);r=eulerphi(r));hilf=14^15;forstep(j=13,2,-1,r=x[j
-1];if(r>=2,hilf=powmod(j,hilf,r);w=factorint(r);w=component(w,2);while(hilf<vec
max(w),hilf=hilf+r))));component(Mod(hilf,r),2)
? tower2
%20 = (p,q,r)->if(q==0,hilf=1);if(q==1,hilf=p);if(q==2,hilf=powmod(p,p,r));if(q>
2,x=[];for(j=1,q,x=concat(x,r);r=eulerphi(r));hilf=3^2;forstep(j=13,2,-1,r=x[j-1
];if(r>=2,hilf=powmod(17-j,hilf,r);w=factorint(r);w=component(w,2);while(hilf<ve
cmax(w),hilf=hilf+r))));component(Mod(hilf,r),2)
?
The reason your code doesn't work is that you (recursively) compute x^n (mod r) as x^(n mod phi(r)) and this isn't true unless gcd(x,r) = 1.
Also, you don't need powmod since Mod(basis,modul)^expo is built-in.
Here's a general possibility :
\\ x[1]^(x[2]^( ...^ x[#x])) mod m, assuming x[i] > 1 for all i
tower(x, m) =
{ my(f = factor(m), P = f[,1], E = f[,2]);
chinese(vector(#P, i, towerp(x, P[i], E[i])));
}
towerp(x, p, e) =
{ my(q = p^e, i, t, v);
if (#x == 0, return (Mod(1, q)));
if (#x == 1, return (Mod(x[1], q)));
if (v = valuation(x[1], p),
t = x[#x]; i = #x;
while (i > 1,
if (t >= e, return (Mod(0, q)));
t = x[i]^t; i--);
if (t * v >= e, return (Mod(0, q)));
return (Mod(x[1], q)^t);
);
Mod(x[1], q)^lift(tower(x[2..#x], (p-1)*p^e));
}
? tower([2..15], 163)
%1 = Mod(162, 163)
? tower(Vecrev([2..15]), 163)
%2 = Mod(16, 163)
I need to find the length of the longest common subsequence.
s and t are Strings, and n and m are their lengths. I would like to write a recursive code.
This is what I did so far but I cant get any progress:
def lcs_len_v1(s, t):
n = len(s)
m = len(t)
return lcs_len_rec(s,n,t,m)
def lcs_len_rec(s,size_s,t,size_t):
cnt= 0
if size_s==0 or size_t==0:
return 0
elif s[0]==t[0]:
cnt= +1
return cnt, lcs_len_rec(s[1:], len(s[1:]), t[1:], len(t[1:]))
This works:
def lcs(xstr, ystr):
if not xstr or not ystr:
return ""
x, xs, y, ys = xstr[0], xstr[1:], ystr[0], ystr[1:]
if x == y:
return x + lcs(xs, ys)
else:
return max(lcs(xstr, ys), lcs(xs, ystr), key=len)
print(lcs("AAAABCC","AAAACCB"))
# AAAACC
You should know that a recursive approach will only work with relatively trivial string; the complexity increases very rapidly with longer strings.
this is my code, how can I use on it the memoization technique?
def lcs_len_v1(s, t):
n = len(s)
m = len(t)
return lcs_len_rec(s,n,t,m)
def lcs_len_rec(s,size_s,t,size_t):
if size_s==0 or size_t==0:
return 0
elif s[0]==t[0]:
cnt=0
cnt+= 1
return cnt+ lcs_len_rec(s[1:], size_s-1, t[1:], size_t-1)
else:
return max(lcs_len_rec(s[1:], size_s-1, t, size_t), lcs_len_rec(s, size_s, t[1:], size_t-1))
Using the memoization technique, you can run the algorithm also with a very long strings. Infact it is just O(n^2):
def recursiveLCS(table, s1, s2):
if(table[len(s1)][len(s2)] != False):
return table[len(s1)][len(s2)]
elif len(s1) == 0 or len(s2) == 0:
val = ""
elif s1[0] == s2[0]:
val = s1[0] + recursiveLCS(table, s1[1:], s2[1:])
else:
res1 = recursiveLCS(table, s1[1:], s2)
res2 = recursiveLCS(table, s1, s2[1:])
val = res2
if len(res1) > len(res2):
val = res1
table[len(s1)][len(s2)] = val
return val
def computeLCS(s1, s2):
table = [[False for col in range(len(s2) + 1)] for row in range(len(s1) + 1)]
return recursiveLCS(table, s1, s2)
print computeLCS("testistest", "this_is_a_long_testtest_for_testing_the_algorithm")
Output:
teststest