Skip to content

Instantly share code, notes, and snippets.

@longdog
Last active July 7, 2021 12:56
Show Gist options
  • Save longdog/561dfd764497d3bee70af527eccae4f3 to your computer and use it in GitHub Desktop.
Save longdog/561dfd764497d3bee70af527eccae4f3 to your computer and use it in GitHub Desktop.
fun same_string(s1 : string, s2 : string) =
s1 = s2
fun all_except_option(s:string, ss:string list) =
let fun acc(prevs, nexts) =
case nexts of
[] => NONE
| n'::nexts' => if same_string(s,n') then SOME(prevs @ nexts') else acc(n'::prevs, nexts')
in
acc([],ss)
end
fun get_substitutions1(sss: string list list, s:string) =
case sss of
[] => []
| ss::sss' => case all_except_option(s, ss) of
SOME ss' => ss' @ get_substitutions1(sss',s)
| _=> get_substitutions1(sss',s)
fun get_substitutions2(sss: string list list, s:string) =
let fun sub(acc:string list, strs: string list list) =
case strs of
[] => acc
| ss::sss' => case all_except_option(s, ss) of
SOME ss' => sub(acc @ ss' , sss')
| _ => sub(acc, sss')
in
sub([], sss)
end
fun similar_names(sss: string list list, {first:string, last:string, middle:string}) =
let
fun get_records(acc:{first:string, last:string, middle:string} list, ns:string list) =
case ns of
[] => acc
| n::ns' => get_records(acc @ [{first = n, last = last, middle = middle}], ns')
in
get_records([], (first :: get_substitutions2(sss, first)))
end
datatype suit = Clubs | Diamonds | Hearts | Spades
datatype rank = Jack | Queen | King | Ace | Num of int
type card = suit * rank
datatype color = Red | Black
datatype move = Discard of card | Draw
exception IllegalMove
fun card_color c =
case c of
((Clubs | Spades),_) => Black
| _ => Red
fun card_value c =
case c of
(_, Num x) => x
| (_, Ace) => 11
| _ => 10
fun remove_card(cs, c, e) =
let fun acc(prevs, nexts) =
case nexts of
[] => raise e
| n'::nexts' => if c=n' then prevs @ nexts' else acc(n'::prevs, nexts')
in
acc([],cs)
end
fun all_same_color cs =
case cs of
[] => true
| c::[] => true
| c1::c2::cs' => card_color(c1)=card_color(c2) andalso all_same_color (c2::cs')
fun sum_cards cs =
let fun sum (acc, cs') =
case cs' of
[] => acc
| c::cs'' => sum(card_value(c) + acc, cs'')
in sum(0,cs)
end
fun score (cs, goal) =
let
val sum = sum_cards cs
val sum' = if sum > goal then 3 * (sum - goal) else goal - sum
in
if all_same_color(cs) then sum' div 2 else sum'
end
fun officiate (cs, ms, goal) =
let
fun hold(cs1, cs2) =
case cs1 of
[] => NONE
| c1::cs1' => SOME((cs1', c1::cs2))
fun game(hcs, cs', ms') =
case ms' of
[] => score(hcs, goal)
| (Discard c)::ms'' => game(remove_card(hcs,c,IllegalMove), cs', ms'')
| (Draw)::ms'' => case hold(cs', hcs) of
NONE => game(hcs,cs',[])
| SOME(cs'',hcs') => if sum_cards(hcs') >= goal then game(hcs',cs'',[]) else game(hcs',cs'',ms'')
in
game([], cs, ms)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment