TUM: Numerical Programming Summary
An incomplete(!) summary/cheatsheet I wrote as exam prep for NumProg in the 2021 winter semester!
⚠️ No guarantee of correctness! May contain errors! ⚠️
An incomplete(!) summary/cheatsheet I wrote as exam prep for NumProg in the 2021 winter semester!
⚠️ No guarantee of correctness! May contain errors! ⚠️
An incomplete(!) summary/cheatsheet I wrote as exam prep for Computational Intelligence (electrical engineering elective) in the 2021 winter semester!
⚠️ No guarantee of correctness! May contain errors! ⚠️
I really should stop making scripts that help me cheat in games that I'm bad at.
The script requires a word list with all candidate words as a text file.
Type your guess, then the color result that you got (e.g. ggybg for green-green-yellow-black-green).
The script will then spit out all possible candidate words (as long as they're in the dictionary).
Supports any number of simultaneous games such as Quordle.
from functools import *
def satisfies(word, green, yellow, black):
return all(word[pos] == letter for letter, pos in green.items()) \
and all(letter in word and word[pos] != letter for letter, pos in yellow.items()) \
and all(letter not in word for letter in black)
words_file = open('wordle.txt', 'r')
words = {word.strip().lower() for word in words_file if len(word.strip()) == 5}
print('How many simultaneous games? (wordle=1, quordle=4)')
num = int(input())
candidates = [list(words) for i in range(num)]
green = [dict() for i in range(num)]
yellow = [dict() for i in range(num)]
black = [set() for i in range(num)]
finished = [False for i in range(num)]
while True:
print('Type Guess:')
guess = input()
if guess.lower() == 'done':
break
for n in range(num):
if finished[n]:
continue
print(f'Type result for game {n+1} ([g]reen, [y]ellow, [b]lack):')
result = input()
if result == 'ggggg':
finished[n] = True
continue
for i in range(5):
match result[i]:
case 'g':
green[n][guess[i]] = i #this letter is at this pos
case 'y':
yellow[n][guess[i]] = i #this letter is NOT at this pos
case 'b':
black[n].add(guess[i]) #this letter is not at all
black[n] = {w for w in black[n] if w not in green[n]} #cleanse
#print('g=', green[n], 'y=', yellow[n], 'b=', black[n])
candidates[n] = [word for word in candidates[n] if satisfies(word, green[n], yellow[n], black[n])]
print('Candidates:', candidates[n])
if num > 1:
print('Candidates with max num:')
all_cand = reduce(lambda a, b: a + b, [candidates[i] for i in range(n) if not finished[i]], [])
all_cand = {word: all_cand.count(word) for word in all_cand}
print(dict(sorted(all_cand.items(), key=lambda kv: kv[1])))
Don't forget to enable "Interactive Mode" if you're running this in JDoodle.
Also, you'd need to upload a wordle.txt file using the upload button right next to the 'Execute' buton.
I am very bad at two things: card games and mental arithmetic. After losing a dozen games in a row to my girlfriend, I decided to write a Haskell script that will solve the game for me.
The card game 24 works like this:
1. Draw 4 random cards from a deck.
2. Find an integer expression consisting of the numbers on the card.
3. If you play in a group, the slowest one must pick one of the others who supposedly know the
solution.
4. If the selected player answers correctly, the slowest one takes a shot. If the selected player
was bluffing, they take two shots.
import Data.Maybe
import Data.List
ops :: [(Double -> Double -> Double, String -> String -> String)]
ops = [
((+), \a b -> a++"+"++b),
((-), \a b -> a++"-"++b),
((*), \a b -> a++"*"++b),
((/), \a b -> a++"/"++b),
((**), \a b -> a++"^"++b),
(\a b -> a ** (1/b), \a b -> a++"of "++b++"th root ")]
check24 :: [Double] -> Maybe String
check24 [] = Nothing
check24 [x] = if x == 24 then Just "" else Nothing
check24 (x:y:ls) = findFirst ops
where
findFirst [] = Nothing
findFirst ((op, toStr):ops) = case check24 (op x y : ls) of
Nothing -> findFirst ops
Just res -> Just (toStr (if length ls == 2 then "(((" ++ show x else "") (show y) ++ ")" ++ res)
exists :: [Double] -> Bool
exists [] = False
exists [x] = if x == 24 then True else False
exists (x:y:ls) = findFirst ops
where
findFirst [] = False
findFirst ((op, toStr):ops) = if exists (op x y : ls)
then True
else findFirst ops
checkAll list = catMaybes [check24 p | p <- permutations list]
existsAll list = filter (==True) [exists p | p <- permutations list]
main = do
let solutions = checkAll [2, 4, 5, 7] -- all solutions of cards 2, 4, 5, 7 that results in 24
putStrLn "Expressions that result in 24:"
mapM_ putStrLn solutions
If you've taken GDB at TUM you'll know what this is. As faithful to the pseudocode implementation found in the lecture slides as I could make. One of my first python scripts, had a lot of fun discovering convenient python features.
import functools
import operator
import copy
from collections import defaultdict
from itertools import chain, combinations
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
def setify(FDs):
# convert each FD from string -> string to set -> set
return [(set(left), set(right)) for (left, right) in FDs]
def stringify(FDs):
# convert each FD from set -> set to string -> string
return [(', '.join(sorted(left)), ', '.join(sorted(right))) for (left, right) in FDs]
def is_superkey(R, FDs, key):
return attribute_cover(FDs, key) == R
def find_candidate_keys(R, FDs):
# EXTREMELY INEFFICIENT BRUTE FORCE SOLUTION!!!! O(2^n)!!!!!!!!!!!!!!!!!!!!!
# FDs should preferably be already canoninized to increase efficiency
# find all attributes who could be part of a key, i.e. it appears on the left side of a FD OR it never appears on the right side of any FD
attributes = {a for (left, right) in FDs for a in left} | {
a for a in R if not any([a in right for (left, right) in FDs])}
# for all subsets of attributes, check if it's a candidate key, i.e. it's a superkey that is not a proper superset of another key
candidates = []
for key in powerset(attributes):
if not any([set(c) < set(key) for c in candidates]) and is_superkey(R, FDs, set(key)):
candidates.append(tuple(sorted(key)))
return candidates
def attribute_cover(FDs, attributes):
result = set(attributes)
changed = True
while(changed):
changed = False
for (left, right) in FDs:
if left <= result and not (right <= result):
result |= right
changed = True
return result
def canonical_cover(FDs):
# FDs = copy.deepcopy(FDs) # using this won't permanently change input FDs
# left reduction
for i in range(len(FDs)):
left, right = FDs[i]
for a in left:
if right <= attribute_cover(FDs, left - {a}):
FDs[i] = (left - {a}, right)
print('Left Reduction:')
for (left, right) in (stringify(FDs)):
print(left, '->', right)
# right reduction
for i in range(len(FDs)):
left, right = FDs[i]
for b in list(right):
right -= {b}
FDs[i] = (left, right)
if b not in attribute_cover(FDs, left):
right |= {b}
FDs[i] = (left, right)
print('Right Reduction:')
for (left, right) in (stringify(FDs)):
print(left, '->', right)
# remove trivial (right side empty) FDs
FDs = [(frozenset(left), right) for (left, right) in FDs if len(right) > 0]
# unite same left sides
d = defaultdict(set)
for l, r in FDs:
d[l] |= r
FDs = list(d.items())
print('Unify:')
for (left, right) in (stringify(FDs)):
print(left, '->', right)
return FDs
def synthesize(R, FDs):
FDs = canonical_cover(FDs)
# transform FDs into relations
relations = set()
for left, right in FDs:
r = tuple(left) + tuple(right)
if not any([set(r) <= set(x) for x in relations]):
relations.add(r)
# if none of the relations contain keys to R, then create a relation of the key
candidate_keys = find_candidate_keys(R, FDs)
if not any([set(key) <= set(r) for key in candidate_keys for r in relations]):
print('Manually adding a minimal candidate key to the relation!')
relations.add(min(candidate_keys))
return FDs, candidate_keys, relations
example = (
# R =
# Format: {'A', 'B', 'C'} === set('ABC')
set('ABCDE'),
# FDs =
# Format: Left -> Right === (Left, Right)
setify([
('BD', 'CE'),
('CE', 'BD'),
('CD', 'AE'),
('D', 'ABE'),
('BC', 'AD')
])
)
R, FDs = example
Fc, candidate_keys, relations = synthesize(R, FDs)
print('\nCanonical Cover:')
for (left, right) in (stringify(Fc)):
print(left, '->', right)
print('\nCandidate Keys:')
for key in sorted(candidate_keys):
print('(' + ', '.join(key) + ')')
print('\nSynthesized Relations:')
for r in relations:
print('{[' + ', '.join(r) + ']}')