dump
This commit is contained in:
parent
22ef750437
commit
028fb0bc3a
180
.gitignore
vendored
Normal file
180
.gitignore
vendored
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# Dom's manually added things
|
||||||
|
bad apple/factorio-draftsman
|
||||||
|
typing-puzzles/
|
||||||
|
heartbound OCR/
|
||||||
|
signals/
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
#uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||||
|
.pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
152
1-2-3-digit-addend-662288000.py
Normal file
152
1-2-3-digit-addend-662288000.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
from functools import cache
|
||||||
|
from collections import Counter, defaultdict
|
||||||
|
|
||||||
|
# pool = Counter(map(int, "000226688"))
|
||||||
|
# counted_digits = (0, 2, 6, 8)
|
||||||
|
# counts = (3, 2, 2, 2)
|
||||||
|
|
||||||
|
# 268
|
||||||
|
|
||||||
|
# 208
|
||||||
|
# 60
|
||||||
|
# 0
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def choose_n_unique(counts, n):
|
||||||
|
if sum(counts) < n:
|
||||||
|
raise "you done fucked up"
|
||||||
|
if sum(counts) == n:
|
||||||
|
return set([counts])
|
||||||
|
out = set([])
|
||||||
|
for i, count in enumerate(counts):
|
||||||
|
if count <= 0:
|
||||||
|
continue
|
||||||
|
out.update(
|
||||||
|
choose_n_unique(counts[:i] + (count - 1,) + counts[i + 1 :], n)
|
||||||
|
)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def sub(a, b): # a-b
|
||||||
|
return tuple(x - y for x, y in zip(a, b))
|
||||||
|
|
||||||
|
|
||||||
|
# print(choose_n_unique(counts, 3))
|
||||||
|
# print(find_sums(counts))
|
||||||
|
# print(possible_sums((3, 2, 2, 2)))
|
||||||
|
|
||||||
|
|
||||||
|
def has_len_digit(tup, length):
|
||||||
|
for t in tup:
|
||||||
|
if len(str(t)) == length:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# tup_0, tup_1 = (826,), (0, 0, 6, 820)
|
||||||
|
|
||||||
|
# print(has_len_digit(tup_0, 2))
|
||||||
|
# print(has_len_digit(tup_1, 2))
|
||||||
|
# exit()
|
||||||
|
|
||||||
|
|
||||||
|
def find_solutions(counted_digits, counts):
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def possible_sums(counts): # sum -> set(tuple(addend))
|
||||||
|
if sum(counts) == 0:
|
||||||
|
return {0: set()}
|
||||||
|
if sum(counts) == 1:
|
||||||
|
for i, count in enumerate(counts):
|
||||||
|
if count == 0:
|
||||||
|
continue
|
||||||
|
digit = counted_digits[i]
|
||||||
|
out = {digit: set([(digit,)])}
|
||||||
|
return out
|
||||||
|
|
||||||
|
out = defaultdict(set)
|
||||||
|
|
||||||
|
for i, count in enumerate(counts):
|
||||||
|
if count <= 0:
|
||||||
|
continue
|
||||||
|
digit = counted_digits[i]
|
||||||
|
sub = possible_sums(counts[:i] + (count - 1,) + counts[i + 1 :])
|
||||||
|
for s, tups in sub.items():
|
||||||
|
for tup in tups:
|
||||||
|
out[s + digit].add(tuple(sorted((digit,) + tup)))
|
||||||
|
# try appending the digit to all sub subms
|
||||||
|
for tups in sub.values():
|
||||||
|
for tup in tups:
|
||||||
|
for j, val in enumerate(tup):
|
||||||
|
if j > 0 and val == tup[j - 1]:
|
||||||
|
continue
|
||||||
|
new_tup = tuple(
|
||||||
|
sorted((val * 10 + digit,) + tup[:j] + tup[j + 1 :])
|
||||||
|
)
|
||||||
|
out[sum(new_tup)].add(new_tup)
|
||||||
|
return out
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for counts_0 in choose_n_unique(counts, 3):
|
||||||
|
counts_1 = sub(counts, counts_0)
|
||||||
|
# print(counts_1)
|
||||||
|
possible_0 = possible_sums(counts_0)
|
||||||
|
possible_1 = possible_sums(counts_1)
|
||||||
|
# print(possible_0.get(268, "nope"))
|
||||||
|
# print(possible_1.get(268, "nope"))
|
||||||
|
# print()
|
||||||
|
for total in possible_0.keys() & possible_1.keys():
|
||||||
|
tups_0 = possible_0[total]
|
||||||
|
tups_1 = possible_1[total]
|
||||||
|
for tup_0 in tups_0:
|
||||||
|
for tup_1 in tups_1:
|
||||||
|
if not (has_len_digit(tup_0, 1) or has_len_digit(tup_1, 1)):
|
||||||
|
continue
|
||||||
|
if not (has_len_digit(tup_0, 2) or has_len_digit(tup_1, 2)):
|
||||||
|
continue
|
||||||
|
if not (has_len_digit(tup_0, 3) or has_len_digit(tup_1, 3)):
|
||||||
|
continue
|
||||||
|
out.append((tup_0, tup_1))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
# print(find_solutions(counted_digits=(0, 2, 6, 8), counts=(3, 2, 2, 2)))
|
||||||
|
import random
|
||||||
|
|
||||||
|
rng = random.Random(4)
|
||||||
|
# best = 100
|
||||||
|
# for i in range(1000):
|
||||||
|
|
||||||
|
# # rng.randint()
|
||||||
|
# def r(radius):
|
||||||
|
# return rng.randint(-radius, radius)
|
||||||
|
|
||||||
|
# candidate = find_solutions(
|
||||||
|
# counted_digits=(1 + r(1), 2 + r(1), 6 + r(1), 8 + r(1)),
|
||||||
|
# counts=(3 + r(1), 2 + r(1), 2 + r(1), 2 + r(1)),
|
||||||
|
# )
|
||||||
|
# if not candidate:
|
||||||
|
# continue
|
||||||
|
|
||||||
|
# if len(candidate) <= best:
|
||||||
|
# best = len(candidate)
|
||||||
|
# print("yay")
|
||||||
|
# for tup in candidate:
|
||||||
|
# print(" ", tup)
|
||||||
|
|
||||||
|
|
||||||
|
def counted_digits_and_counts_from_solution(solution):
|
||||||
|
s = str(solution)
|
||||||
|
for to_remove in "(), ":
|
||||||
|
s = s.replace(to_remove, "")
|
||||||
|
print(s)
|
||||||
|
print("".join(sorted(s)))
|
||||||
|
c = Counter(s)
|
||||||
|
counted_digits = tuple(int(k) for k in sorted(c))
|
||||||
|
counts = tuple(int(c[k]) for k in sorted(c))
|
||||||
|
return counted_digits, counts
|
||||||
|
|
||||||
|
|
||||||
|
print(counted_digits_and_counts_from_solution("((261,), (7, 27, 227)))"))
|
||||||
|
print(find_solutions((1, 2, 6, 7), (1, 4, 1, 3)))
|
10
12345_combination_sum.py
Normal file
10
12345_combination_sum.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import math
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
# print(list))
|
||||||
|
|
||||||
|
start_digits = [1,2,3,4,5]
|
||||||
|
|
||||||
|
print(sum(int(''.join(str(digit) for digit in digits)) for digits in itertools.permutations(start_digits)))
|
||||||
|
|
||||||
|
print(math.factorial(len(start_digits)) * (sum(start_digits)/len(start_digits)) * 11111)
|
180
3b1b cessboard encoding puzzle.py
Normal file
180
3b1b cessboard encoding puzzle.py
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# https://youtu.be/wTJI_WuZSwE
|
||||||
|
|
||||||
|
from functools import reduce, cache
|
||||||
|
from typing import List, Tuple, Callable, Iterable
|
||||||
|
from math import sqrt, log2
|
||||||
|
from random import Random
|
||||||
|
|
||||||
|
def get_flip_pos_2x2(board: List[int], key: int) -> int:
|
||||||
|
assert all(x in [0,1] for x in board)
|
||||||
|
assert len(board) == 4
|
||||||
|
s = sum(board)
|
||||||
|
if s==0:
|
||||||
|
return key
|
||||||
|
if s==1:
|
||||||
|
pos = board.index(1)
|
||||||
|
if key == 0:
|
||||||
|
return pos # empty
|
||||||
|
if key == 1:
|
||||||
|
return [1,0,3,2][pos] # horizontal
|
||||||
|
if key == 2:
|
||||||
|
return [2,3,0,1][pos] # vertical
|
||||||
|
if key == 3:
|
||||||
|
return [3,2,1,0][pos] # diagonal
|
||||||
|
assert False
|
||||||
|
if s==2:
|
||||||
|
# ensure ``sum(board) in [1,3]``, pointing to key
|
||||||
|
if board[key] == 0: # sum(flipped board) == 3
|
||||||
|
possibilities = [i for i in range(len(board)) if i != key and board[i]==0]
|
||||||
|
else: # sum(flipped board) == 3
|
||||||
|
possibilities = [i for i in range(len(board)) if i != key and board[i]==1]
|
||||||
|
assert len(possibilities) == 1
|
||||||
|
return possibilities[0]
|
||||||
|
if s==3:
|
||||||
|
return get_flip_pos_2x2(all_flipped(board), key)
|
||||||
|
if s==4:
|
||||||
|
return get_flip_pos_2x2(all_flipped(board), key)
|
||||||
|
assert False
|
||||||
|
|
||||||
|
def all_flipped(board: List[int]) -> List[int]:
|
||||||
|
return [1-x for x in board]
|
||||||
|
|
||||||
|
def guess_key_2x2(board: List[int]) -> int:
|
||||||
|
s = sum(board)
|
||||||
|
if s==0:
|
||||||
|
return 0
|
||||||
|
if s==1:
|
||||||
|
return board.index(1)
|
||||||
|
if s==2:
|
||||||
|
if board==[1,1,0,0] or board==[0,0,1,1]:
|
||||||
|
return 1 # horizontal
|
||||||
|
if board==[1,0,1,0] or board==[0,1,0,1]:
|
||||||
|
return 2 # vertical
|
||||||
|
if board==[1,0,0,1] or board==[0,1,1,0]:
|
||||||
|
return 3 # diagonal
|
||||||
|
if s==3:
|
||||||
|
return guess_key_2x2(all_flipped(board))
|
||||||
|
if s==4:
|
||||||
|
return guess_key_2x2(all_flipped(board))
|
||||||
|
assert False
|
||||||
|
|
||||||
|
|
||||||
|
def flip_mutate(board: List[int], flip_pos: int):
|
||||||
|
board[flip_pos] = 1-board[flip_pos]
|
||||||
|
|
||||||
|
def flip_copy(board: List[int], flip_pos: int) -> List[int]:
|
||||||
|
board = board[:]
|
||||||
|
flip_mutate(board, flip_pos)
|
||||||
|
return board
|
||||||
|
|
||||||
|
def print_board(board: List[int]):
|
||||||
|
sidelength = sqrt(len(board))
|
||||||
|
assert sidelength == int(sidelength)
|
||||||
|
sidelength = int(sidelength)
|
||||||
|
for row_i in range(sidelength):
|
||||||
|
print(''.join(str(x) for x in board[row_i*sidelength:(row_i+1)*sidelength]))
|
||||||
|
|
||||||
|
def generate_boards(board_squre_count: int, sample_count: int) -> Iterable[int]:
|
||||||
|
if sample_count >= 2**board_squre_count:
|
||||||
|
print('doing exhaustive verification.')
|
||||||
|
yield from range(2**board_squre_count)
|
||||||
|
print(f'not doing exhaustive. need sample_count>={2**board_squre_count}, got sample_count={sample_count}')
|
||||||
|
rng = Random(4)
|
||||||
|
for i in range(sample_count):
|
||||||
|
yield rng.getrandbits(board_squre_count)
|
||||||
|
|
||||||
|
|
||||||
|
def validate(board_squre_count, get_flip_pos: Callable, guess_key: Callable, sample_count=2**16) -> bool:
|
||||||
|
success_boards = set()
|
||||||
|
|
||||||
|
for sample_i, board_int in enumerate(generate_boards(board_squre_count, sample_count)):
|
||||||
|
if board_int in success_boards:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if sample_i %100 == 0:
|
||||||
|
print(sample_i/sample_count)
|
||||||
|
for key in range(board_squre_count):
|
||||||
|
# potential optimization: could re-use board and unflip guess
|
||||||
|
board = [(board_int>>i)&1 for i in reversed(range(board_squre_count))]
|
||||||
|
|
||||||
|
flip_pos = get_flip_pos(board, key)
|
||||||
|
flip_mutate(board, flip_pos)
|
||||||
|
guess = guess_key(board)
|
||||||
|
if guess != key:
|
||||||
|
print(f'Found counter example. Got guess {guess}, want {key}')
|
||||||
|
flip_mutate(board, flip_pos)
|
||||||
|
print('before flip:')
|
||||||
|
print_board(board)
|
||||||
|
flip_mutate(board, flip_pos)
|
||||||
|
print('after flip:')
|
||||||
|
print_board(board)
|
||||||
|
return False
|
||||||
|
|
||||||
|
success_boards.add(board_int)
|
||||||
|
if len(success_boards) == 2**board_squre_count:
|
||||||
|
# All boards have been validated
|
||||||
|
print('exhaustive, yay')
|
||||||
|
return True
|
||||||
|
print(f'non exhaustive finish. covered {len(success_boards)} cases ({len(success_boards) / 2**board_squre_count:%} of cases) successfully')
|
||||||
|
return True
|
||||||
|
|
||||||
|
# validate(4, get_flip_pos_2x2, guess_key_2x2)
|
||||||
|
|
||||||
|
# Scaler possibilities:
|
||||||
|
# Total key index % 4 if we split into 4-squares
|
||||||
|
# is each reg
|
||||||
|
# XOR each 4x4 section into a bit to determine which quadrant
|
||||||
|
# layer each 4x4 section with XOR, to determine which quadrant in the above 4x4
|
||||||
|
# layer each 2x2 section with XOR, to determine which quadrant in 2x2
|
||||||
|
|
||||||
|
def guess_key_pow2board(board: List[int]) -> int:
|
||||||
|
if len(board) == 4:
|
||||||
|
return guess_key_2x2(board)
|
||||||
|
|
||||||
|
sidelength = sqrt(len(board))
|
||||||
|
assert sidelength == int(sidelength)
|
||||||
|
sidelength = int(sidelength)
|
||||||
|
assert log2(sidelength) == int(log2(sidelength))
|
||||||
|
quarter = len(board) / 4
|
||||||
|
assert quarter == int(quarter)
|
||||||
|
quarter = int(quarter)
|
||||||
|
|
||||||
|
# Not actually quadrants but good enough
|
||||||
|
quadrants = [ board[i*quarter:(i+1)*quarter] for i in range(0,4) ]
|
||||||
|
|
||||||
|
quarter_i = guess_key_2x2([ reduce(lambda a,b: a^b, q) for q in quadrants ])
|
||||||
|
sub_i = guess_key_pow2board([a^b^c^d for a,c,b,d in zip(*quadrants)])
|
||||||
|
return quarter * quarter_i + sub_i
|
||||||
|
|
||||||
|
def make_get_flip_pos(guess_key: Callable) -> Callable:
|
||||||
|
|
||||||
|
# Flip the thing that works
|
||||||
|
def get_flip_pos(board, key) -> int:
|
||||||
|
possibilities = [
|
||||||
|
flip_pos for flip_pos in range(len(board))
|
||||||
|
if guess_key(flip_copy(board, flip_pos)) == key
|
||||||
|
]
|
||||||
|
assert len(possibilities) == 1, f"possibilities={possibilities} want length 1"
|
||||||
|
return possibilities[0]
|
||||||
|
return get_flip_pos
|
||||||
|
|
||||||
|
def get_flip_pos_pow2board(board: List[int], key: int) -> int:
|
||||||
|
if len(board) == 4:
|
||||||
|
return get_flip_pos_2x2(board, key)
|
||||||
|
quarter = len(board) / 4
|
||||||
|
assert quarter == int(quarter)
|
||||||
|
quarter = int(quarter)
|
||||||
|
|
||||||
|
# Not actually quadrants but good enough
|
||||||
|
quadrants = [ board[i*quarter:(i+1)*quarter] for i in range(0,4) ]
|
||||||
|
quarter_i = get_flip_pos_2x2([ reduce(lambda a,b: a^b, q) for q in quadrants ], key//4)
|
||||||
|
sub_i = get_flip_pos_pow2board([a^b^c^d for a,c,b,d in zip(*quadrants)], key%4)
|
||||||
|
return quarter * quarter_i + sub_i
|
||||||
|
|
||||||
|
|
||||||
|
# validate(4, make_get_flip_pos(guess_key_2x2), guess_key_2x2)
|
||||||
|
# validate(16, make_get_flip_pos(guess_key_pow2board), guess_key_pow2board)
|
||||||
|
# validate(16, get_flip_pos_pow2board, guess_key_pow2board)
|
||||||
|
validate(64, get_flip_pos_pow2board, guess_key_pow2board)
|
||||||
|
# validate(64, make_get_flip_pos(guess_key_pow2board), guess_key_pow2board)
|
||||||
|
|
86
Can you solve the rogue submarine riddle.py
Normal file
86
Can you solve the rogue submarine riddle.py
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
from collections import Counter
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
basis = [1,2,3,4,5,6]
|
||||||
|
|
||||||
|
def get_all_subsets(l):
|
||||||
|
if l == []:
|
||||||
|
return [[]]
|
||||||
|
subs = get_all_subsets(l[1:])
|
||||||
|
return subs + [[l[0]] + el for el in subs]
|
||||||
|
|
||||||
|
all_subsets = get_all_subsets(basis)
|
||||||
|
all_subsets = sorted([sub for sub in all_subsets if len(sub) >= 2])
|
||||||
|
# all_subsets = sorted([sub for sub in all_subsets if len(sub) >= 2])
|
||||||
|
# all_subsets = sorted([sub for sub in all_subsets if sum(sub) < 9])
|
||||||
|
|
||||||
|
def product(sub):
|
||||||
|
if len(sub) == 0:
|
||||||
|
return 1
|
||||||
|
return sub[0] * product(sub[1:])
|
||||||
|
|
||||||
|
def sort_keys(counter: Counter) -> Counter:
|
||||||
|
out = Counter()
|
||||||
|
for key in sorted(counter.keys()):
|
||||||
|
out[key] = counter[key]
|
||||||
|
return out
|
||||||
|
|
||||||
|
def print_sorted_by_key(counter: Counter) -> Counter:
|
||||||
|
print('{')
|
||||||
|
for key in sorted(counter.keys()):
|
||||||
|
print(f' {key}: {counter[key]},')
|
||||||
|
print('}')
|
||||||
|
|
||||||
|
|
||||||
|
sum_counter = Counter(sum(sub) for sub in all_subsets)
|
||||||
|
product_counter = Counter(product(sub) for sub in all_subsets)
|
||||||
|
product_counter_unique_sum = Counter(product(sub) for sub in all_subsets if sum_counter[sum(sub)] > 1)
|
||||||
|
|
||||||
|
#debug
|
||||||
|
print_sorted_by_key(sum_counter)
|
||||||
|
print_sorted_by_key(product_counter)
|
||||||
|
|
||||||
|
print(sum([3,4,5,6]))
|
||||||
|
print(product([3,4,5,6]))
|
||||||
|
print('a', [(sub, sum(sub)) for sub in all_subsets if sum(sub)==18])
|
||||||
|
print('b', [(sub, product(sub)) for sub in all_subsets if product(sub)==360])
|
||||||
|
print(sum([3,4,5,6]))
|
||||||
|
print(sum([1,3,4,5,6]))
|
||||||
|
|
||||||
|
|
||||||
|
print('xxx')
|
||||||
|
|
||||||
|
# solve it one way
|
||||||
|
for sub in all_subsets:
|
||||||
|
if sum_counter[sum(sub)] > 1 and product_counter_unique_sum[product(sub)] == 1:
|
||||||
|
print(sub, sum(sub), product(sub))
|
||||||
|
|
||||||
|
print('xxx')
|
||||||
|
|
||||||
|
# solve it one way
|
||||||
|
for sub in all_subsets:
|
||||||
|
if sum_counter[sum(sub)] > 1 and product_counter[product(sub)] == 1:
|
||||||
|
print(sub, sum(sub), product(sub))
|
||||||
|
|
||||||
|
print('yyy')
|
||||||
|
|
||||||
|
# solve it another way
|
||||||
|
for answer_sum in range(100):
|
||||||
|
if sum_counter[answer_sum] == 0:
|
||||||
|
continue
|
||||||
|
has_some_determined = False
|
||||||
|
has_some_undetermined = False
|
||||||
|
for sub in all_subsets:
|
||||||
|
if not sum(sub) == answer_sum:
|
||||||
|
continue
|
||||||
|
if product_counter[product(sub)] > 1:
|
||||||
|
has_some_undetermined += True
|
||||||
|
if product_counter[product(sub)] == 1:
|
||||||
|
has_some_determined += True
|
||||||
|
|
||||||
|
if not (has_some_determined and has_some_undetermined):
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(answer_sum, has_some_determined, has_some_undetermined)
|
||||||
|
# print(sub, sum(sub), product(sub))
|
||||||
|
# print()
|
148
Dongle's Difficult Dilemma.py
Normal file
148
Dongle's Difficult Dilemma.py
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# https://www.youtube.com/watch?v=8xXslshomOs
|
||||||
|
from typing import Dict, Optional
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, order=True)
|
||||||
|
class State:
|
||||||
|
gold_a: int
|
||||||
|
gold_b: int
|
||||||
|
silver_a: int
|
||||||
|
silver_b: int
|
||||||
|
gems_a: int
|
||||||
|
gems_b: int
|
||||||
|
equal_priority: bool # 0 means "a", which is the protagonist
|
||||||
|
|
||||||
|
|
||||||
|
winner_cache : Dict[State, int] = {}
|
||||||
|
|
||||||
|
def resolve_auction(state: State, bet_a: int, bet_b: int) -> Optional[State]:
|
||||||
|
if bet_b > state.gems_b:
|
||||||
|
return None
|
||||||
|
assert bet_a <= state.gems_a
|
||||||
|
|
||||||
|
equal_priority = state.equal_priority
|
||||||
|
if bet_a > bet_b:
|
||||||
|
bet_winner = 0
|
||||||
|
elif bet_a < bet_b:
|
||||||
|
bet_winner = 1
|
||||||
|
else:
|
||||||
|
bet_winner = int(equal_priority)
|
||||||
|
equal_priority = 1 - equal_priority
|
||||||
|
|
||||||
|
doing_golds = state.gold_a + state.gold_b <3
|
||||||
|
return State(
|
||||||
|
gold_a=state.gold_a + 1 if doing_golds and bet_winner == 0 else state.gold_a,
|
||||||
|
gold_b=state.gold_b + 1 if doing_golds and bet_winner == 1 else state.gold_b,
|
||||||
|
silver_a=state.silver_a + 1 if not doing_golds and bet_winner == 0 else state.silver_a,
|
||||||
|
silver_b=state.silver_b + 1 if not doing_golds and bet_winner == 1 else state.silver_b,
|
||||||
|
gems_a=state.gems_a - bet_a if bet_winner == 0 else state.gems_a,
|
||||||
|
gems_b=state.gems_b - bet_b if bet_winner == 1 else state.gems_b,
|
||||||
|
equal_priority=equal_priority,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
next_print = 1
|
||||||
|
|
||||||
|
def get_winner(state: State) -> int:
|
||||||
|
if state.gold_a >= 3:
|
||||||
|
winner_cache[state] = 0; return 0, (state,)
|
||||||
|
if state.gold_b >= 3:
|
||||||
|
winner_cache[state] = 1; return 1, (state,)
|
||||||
|
if state.silver_a >= 3:
|
||||||
|
winner_cache[state] = 0; return 0, (state,)
|
||||||
|
if state.silver_b >= 3:
|
||||||
|
winner_cache[state] = 1; return 1, (state,)
|
||||||
|
winner = winner_cache.get(state)
|
||||||
|
if winner is not None:
|
||||||
|
return winner, (state,)
|
||||||
|
|
||||||
|
|
||||||
|
doing_golds = state.gold_a + state.gold_b <3
|
||||||
|
child_states = []
|
||||||
|
path = tuple()
|
||||||
|
|
||||||
|
# minimax
|
||||||
|
winner_a = 1
|
||||||
|
for bet_a in range(state.gems_a+1):
|
||||||
|
(winner_b, path) = max([
|
||||||
|
get_winner(child)
|
||||||
|
for child in
|
||||||
|
[resolve_auction(state, bet_a, bet_b) for bet_b in {0, bet_a, bet_a+1}]
|
||||||
|
if child
|
||||||
|
])
|
||||||
|
winner_a = min(winner_a, winner_b)
|
||||||
|
if winner_a == 0:
|
||||||
|
path = (state, bet_a) + path
|
||||||
|
# break
|
||||||
|
|
||||||
|
winner_cache[state] = winner_a
|
||||||
|
global next_print
|
||||||
|
if len(winner_cache) > next_print:
|
||||||
|
print(len(winner_cache))
|
||||||
|
next_print *= 2
|
||||||
|
|
||||||
|
return winner_a, path
|
||||||
|
|
||||||
|
initial_state = State(
|
||||||
|
gold_a=1,
|
||||||
|
gold_b=0,
|
||||||
|
silver_a=0,
|
||||||
|
silver_b=0,
|
||||||
|
gems_a=75,
|
||||||
|
gems_b=99,
|
||||||
|
equal_priority=0,
|
||||||
|
)
|
||||||
|
import pickle
|
||||||
|
cache_file = __file__+".winner_cache.pickle"
|
||||||
|
|
||||||
|
# print(get_winner(initial_state))
|
||||||
|
# with open(cache_file, 'wb') as f:
|
||||||
|
# pickle.dump(winner_cache, f)
|
||||||
|
|
||||||
|
with open(cache_file, 'rb') as f:
|
||||||
|
winner_cache = pickle.load(f)
|
||||||
|
|
||||||
|
# print(winner_cache)
|
||||||
|
|
||||||
|
def find_children(state):
|
||||||
|
child_states = []
|
||||||
|
for bet_a in range(state.gems_a+1):
|
||||||
|
responses = [resolve_auction(state, bet_a, bet_b) for bet_b in {0, bet_a, bet_a+1}]
|
||||||
|
if any(winner_cache.get(res) == 1 for res in responses):
|
||||||
|
responses = [res for res in responses if winner_cache.get(res) == 1]
|
||||||
|
child_states.extend(responses)
|
||||||
|
return [state for state in child_states if state is not None]
|
||||||
|
|
||||||
|
def find_winning_children(state):
|
||||||
|
return [state for state in find_children(state) if winner_cache.get(state) == 0]
|
||||||
|
|
||||||
|
def print_bets(state0, state1):
|
||||||
|
for bet_a in range(state0.gems_a+1):
|
||||||
|
for bet_b in {0, bet_a, bet_a+1}:
|
||||||
|
res = resolve_auction(state0, bet_a, bet_b)
|
||||||
|
if res == state1:
|
||||||
|
print(f'bet_a={bet_a} bet_b={bet_b}')
|
||||||
|
|
||||||
|
|
||||||
|
def get_winning_path(state: State):
|
||||||
|
get_winning_option_fraction = lambda child: len(find_winning_children(child)) / max(1, len(find_children(child)))
|
||||||
|
print()
|
||||||
|
print(len(find_winning_children(state)), "/", len(find_children(state)))
|
||||||
|
print(state)
|
||||||
|
|
||||||
|
|
||||||
|
winner = winner_cache.get(state)
|
||||||
|
|
||||||
|
child_states = find_winning_children(state)
|
||||||
|
if not child_states:
|
||||||
|
print('fin')
|
||||||
|
return
|
||||||
|
|
||||||
|
choice = min(child_states, key=get_winning_option_fraction)
|
||||||
|
print_bets(state, choice)
|
||||||
|
# for child in child_states:
|
||||||
|
# print(" " + (">" if child is choice else " ") + " " + repr(child))
|
||||||
|
get_winning_path(choice)
|
||||||
|
|
||||||
|
get_winning_path(initial_state)
|
BIN
Dongle's Difficult Dilemma.py.winner_cache.pickle
Normal file
BIN
Dongle's Difficult Dilemma.py.winner_cache.pickle
Normal file
Binary file not shown.
77
bad apple/bad_apple.py
Normal file
77
bad apple/bad_apple.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import pyperclip
|
||||||
|
|
||||||
|
from draftsman.blueprintable import Blueprint, BlueprintBook
|
||||||
|
from draftsman.constants import Direction
|
||||||
|
from draftsman.entity import ConstantCombinator
|
||||||
|
|
||||||
|
# from draftsman.data import items
|
||||||
|
import draftsman.data.signals
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
blueprint = Blueprint()
|
||||||
|
blueprint.label = "bad apple"
|
||||||
|
blueprint.description = "bad apple."
|
||||||
|
blueprint.version = (1, 0) # 1.0
|
||||||
|
|
||||||
|
frame = Image.open("frame.png")
|
||||||
|
threshold = 40
|
||||||
|
signals = list(draftsman.data.signals.raw)[3:] # skip the three special signals
|
||||||
|
|
||||||
|
|
||||||
|
pixels = frame.load()
|
||||||
|
|
||||||
|
# Create the combinator for the single frame
|
||||||
|
frame_combinator = ConstantCombinator()
|
||||||
|
frame_combinator.tile_position = (-1, 0)
|
||||||
|
for x in range(frame.width):
|
||||||
|
column_mask = 0
|
||||||
|
for y in range(frame.height):
|
||||||
|
if pixels[x, y][0] > threshold:
|
||||||
|
column_mask |= 1 << y
|
||||||
|
frame_combinator.set_signal(index=x, signal=signals[x], count=column_mask)
|
||||||
|
blueprint.entities.append(frame_combinator)
|
||||||
|
|
||||||
|
pyperclip.copy(blueprint.to_string())
|
||||||
|
|
||||||
|
# Code for creating the column filters below.
|
||||||
|
|
||||||
|
# for x in range(frame.width):
|
||||||
|
# blueprint.entities.append( # this is our y-combinator :^)
|
||||||
|
# "arithmetic-combinator",
|
||||||
|
# id=f"filter-{x}",
|
||||||
|
# tile_position=[x, 2],
|
||||||
|
# direction=Direction.NORTH,
|
||||||
|
# control_behavior={
|
||||||
|
# "arithmetic_conditions": {
|
||||||
|
# "first_signal": signals[x],
|
||||||
|
# "operation": "AND",
|
||||||
|
# "second_signal": {"type": "virtual", "name": "signal-each"},
|
||||||
|
# "output_signal": {"type": "virtual", "name": "signal-each"},
|
||||||
|
# }
|
||||||
|
# },
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
# arithmetic_conditions = {
|
||||||
|
# "first_signal": {"type": "fluid", "name": "steam"},
|
||||||
|
# "second_signal": {"type": "virtual", "name": "signal-each"},
|
||||||
|
# "operation": "AND",
|
||||||
|
# "output_signal": {"type": "virtual", "name": "signal-each"},
|
||||||
|
# "first_signal_networks": {"red": True, "green": False},
|
||||||
|
# "second_signal_networks": {"red": False, "green": True},
|
||||||
|
# }
|
||||||
|
|
||||||
|
# from draftsman.utils import JSON_to_string
|
||||||
|
|
||||||
|
# # directly hack in these conditions because this is a new feature and we don't care about the validation bullshit
|
||||||
|
# d = blueprint.to_dict()
|
||||||
|
# for entity in d["blueprint"]["entities"]:
|
||||||
|
# entity["control_behavior"]["arithmetic_conditions"][
|
||||||
|
# "first_signal_networks"
|
||||||
|
# ] = {"red": True, "green": False}
|
||||||
|
# entity["control_behavior"]["arithmetic_conditions"][
|
||||||
|
# "second_signal_networks"
|
||||||
|
# ] = {"red": False, "green": True}
|
||||||
|
|
||||||
|
# s = JSON_to_string(d)
|
||||||
|
# pyperclip.copy(str(s))
|
BIN
bad apple/frame.png
Normal file
BIN
bad apple/frame.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 803 B |
60
beltomatic.py
Normal file
60
beltomatic.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# from math import abs
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
max_num = 16
|
||||||
|
initial_nums = list(range(1, max_num + 1))
|
||||||
|
initial_nums.remove(10)
|
||||||
|
|
||||||
|
# end number -> list of steps to get here which are
|
||||||
|
# (prev_number, operation description)
|
||||||
|
|
||||||
|
target = 7387
|
||||||
|
|
||||||
|
upper_bound = target * max_num
|
||||||
|
ops = []
|
||||||
|
for n in initial_nums:
|
||||||
|
ops.append((lambda x, n=n: x + n, f"+{n}"))
|
||||||
|
ops.append((lambda x, n=n: abs(x - n), f"-{n}"))
|
||||||
|
ops.append((lambda x, n=n: x * n, f"*{n}"))
|
||||||
|
ops.append((lambda x, n=n: x // n if x and x % n == 0 else x, f"/{n}"))
|
||||||
|
ops.append((lambda x, n=n: x**n if x**2 < upper_bound else x, f"**{n}"))
|
||||||
|
|
||||||
|
|
||||||
|
seen = {n: [] for n in initial_nums}
|
||||||
|
recent = seen.keys()
|
||||||
|
|
||||||
|
while target not in seen:
|
||||||
|
news = defaultdict(list)
|
||||||
|
for n in recent:
|
||||||
|
for op, description in ops:
|
||||||
|
new = op(n)
|
||||||
|
if new > upper_bound:
|
||||||
|
continue
|
||||||
|
if new in seen:
|
||||||
|
continue
|
||||||
|
news[new].append((n, description))
|
||||||
|
seen.update(news)
|
||||||
|
recent = sorted(news.keys())
|
||||||
|
if not news:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
print(f"progress: {len(seen)=}")
|
||||||
|
|
||||||
|
|
||||||
|
pickers = [
|
||||||
|
lambda l: l[0],
|
||||||
|
lambda l: l[len(l) // 2],
|
||||||
|
lambda l: l[-1],
|
||||||
|
]
|
||||||
|
for picker in pickers:
|
||||||
|
steps = [target]
|
||||||
|
picks = []
|
||||||
|
while prevs := seen[steps[-1]]:
|
||||||
|
pick = picker(prevs)
|
||||||
|
picks.append(pick)
|
||||||
|
steps.append(pick[0])
|
||||||
|
|
||||||
|
print(f"{steps[-1]:>3}", end=" ")
|
||||||
|
for pick in reversed(picks):
|
||||||
|
print(f"{pick[1]:>4}", end=" ")
|
||||||
|
print(f" = {target}")
|
37
cheating royal riddle.py
Normal file
37
cheating royal riddle.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# https://www.youtube.com/watch?v=hk9c7sJ08Bg
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
distribution = {0:1}
|
||||||
|
|
||||||
|
|
||||||
|
def print_sorted_by_key(counter):
|
||||||
|
print('{')
|
||||||
|
for key in sorted(counter.keys()):
|
||||||
|
print(f' {key}: {counter[key]},')
|
||||||
|
print('}')
|
||||||
|
|
||||||
|
def convolve(distribution, equally_weighted_dice):
|
||||||
|
d2 = defaultdict(float)
|
||||||
|
for k,v in distribution.items():
|
||||||
|
for red in equally_weighted_dice:
|
||||||
|
d2[k+red] += v/len(equally_weighted_dice)
|
||||||
|
return d2
|
||||||
|
|
||||||
|
|
||||||
|
for _ in range(20):
|
||||||
|
distribution = convolve(distribution, [2,7,7,12,12, 17])
|
||||||
|
distribution = convolve(distribution, [3,8,8,13,13, 18])
|
||||||
|
|
||||||
|
|
||||||
|
# print_sorted_by_key(distribution)
|
||||||
|
|
||||||
|
cumulative = defaultdict(float)
|
||||||
|
acc = 0
|
||||||
|
for k in sorted(distribution):
|
||||||
|
acc += distribution[k]
|
||||||
|
cumulative[k] = acc
|
||||||
|
|
||||||
|
# print_sorted_by_key(distribution)
|
||||||
|
# print(sum(distribution.values()))
|
||||||
|
print_sorted_by_key(cumulative)
|
55
chef puzzle.py
Normal file
55
chef puzzle.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# https://www.youtube.com/watch?v=HyRjuPP9S3o
|
||||||
|
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
max_val = 1300
|
||||||
|
|
||||||
|
possibilities = list(range(13, max_val+1))
|
||||||
|
|
||||||
|
# exclusions = {64, 729}
|
||||||
|
|
||||||
|
|
||||||
|
perfect_squares = {x*x for x in range(100)}
|
||||||
|
perfect_cubes = {x*x*x for x in range(100) if x*x*x <= max_val}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def less_than_500(x):
|
||||||
|
return x < 500
|
||||||
|
|
||||||
|
def is_perfect_square(x):
|
||||||
|
return x in perfect_squares
|
||||||
|
|
||||||
|
def is_perfect_cube(x):
|
||||||
|
return x in perfect_cubes
|
||||||
|
|
||||||
|
def second_digit_1(x):
|
||||||
|
return str(x)[1] == "1"
|
||||||
|
|
||||||
|
|
||||||
|
# print([x for x in possibilities if is_perfect_cube(x) and is_perfect_square(x)])
|
||||||
|
|
||||||
|
# invert invert second digit is a 1
|
||||||
|
conditions = [less_than_500, is_perfect_square, is_perfect_cube]
|
||||||
|
for mask in range(2**3):
|
||||||
|
pos = set(possibilities)
|
||||||
|
for x in possibilities:
|
||||||
|
for i, condition in enumerate(conditions):
|
||||||
|
if not (condition(x) ^ (mask & (1 << i))):
|
||||||
|
pos.remove(x)
|
||||||
|
break
|
||||||
|
|
||||||
|
if 1 in Counter(second_digit_1(x) for x in pos).values():
|
||||||
|
print(mask, pos)
|
||||||
|
|
||||||
|
# print(mask, pos)
|
||||||
|
|
||||||
|
|
||||||
|
# What was said
|
||||||
|
# it is >500 (lie)
|
||||||
|
# it
|
||||||
|
|
||||||
|
# truth
|
||||||
|
# less than 500
|
||||||
|
# perfect square
|
||||||
|
# perfect
|
114
cnf_or_tuples.py
Normal file
114
cnf_or_tuples.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
################ solver
|
||||||
|
from itertools import chain, combinations
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
|
||||||
|
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 check_solution(selection, operator):
|
||||||
|
return reduce(
|
||||||
|
lambda a, b: tuple(operator(x, y) for x, y in zip(a, b)), selection
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def tuple_selector(tuples, operator):
|
||||||
|
solution_count = 0
|
||||||
|
for selection in powerset(tuples):
|
||||||
|
if not selection:
|
||||||
|
continue
|
||||||
|
if all(check_solution(selection, operator)):
|
||||||
|
print(f"found a solution! {selection}")
|
||||||
|
solution_count += 1
|
||||||
|
print(f"{solution_count=}")
|
||||||
|
|
||||||
|
|
||||||
|
################# problem statement
|
||||||
|
|
||||||
|
|
||||||
|
def operator_with_secret(a: int, b: int) -> int:
|
||||||
|
either = {a, b}
|
||||||
|
if 1 in either:
|
||||||
|
return a + b % 2
|
||||||
|
# if 0 in either:
|
||||||
|
# return 0
|
||||||
|
|
||||||
|
# final element that must be included
|
||||||
|
if 2 in either:
|
||||||
|
# The x's represent free choices.
|
||||||
|
# 0bxxxxxxx00
|
||||||
|
secret = 0b010110100
|
||||||
|
return 3 if secret in either else 0
|
||||||
|
|
||||||
|
# build your own number kit
|
||||||
|
return a | b
|
||||||
|
|
||||||
|
|
||||||
|
tuple_selector(
|
||||||
|
[
|
||||||
|
# make a choice to set a bit in the first number
|
||||||
|
(0b000000100, 0, 1, 0, 0, 0, 0, 0, 0),
|
||||||
|
(0b000001000, 0, 0, 1, 0, 0, 0, 0, 0),
|
||||||
|
(0b000010000, 0, 0, 0, 1, 0, 0, 0, 0),
|
||||||
|
(0b000100000, 0, 0, 0, 0, 1, 0, 0, 0),
|
||||||
|
(0b001000000, 0, 0, 0, 0, 0, 1, 0, 0),
|
||||||
|
(0b010000000, 0, 0, 0, 0, 0, 0, 1, 0),
|
||||||
|
(0b100000000, 0, 0, 0, 0, 0, 0, 0, 1),
|
||||||
|
# .. or not
|
||||||
|
(0b000000000, 0, 1, 0, 0, 0, 0, 0, 0),
|
||||||
|
(0b000000000, 0, 0, 1, 0, 0, 0, 0, 0),
|
||||||
|
(0b000000000, 0, 0, 0, 1, 0, 0, 0, 0),
|
||||||
|
(0b000000000, 0, 0, 0, 0, 1, 0, 0, 0),
|
||||||
|
(0b000000000, 0, 0, 0, 0, 0, 1, 0, 0),
|
||||||
|
(0b000000000, 0, 0, 0, 0, 0, 0, 1, 0),
|
||||||
|
(0b000000000, 0, 0, 0, 0, 0, 0, 0, 1),
|
||||||
|
# this final element that must be included
|
||||||
|
(0b000000010, 1, 0, 0, 0, 0, 0, 0, 0),
|
||||||
|
],
|
||||||
|
operator_with_secret,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Commutative operator variant
|
||||||
|
def operator_with_secret(a: int, b: int) -> int:
|
||||||
|
|
||||||
|
# We're going to create a bitpacked representation of the state of the
|
||||||
|
# computation. The state is the number of records included, and the value
|
||||||
|
# is a bitwise OR of the records included. The state is stored in the
|
||||||
|
# first slot of each tuple, but this operator doesn't know which slot is
|
||||||
|
# first, so we just check to see if the value is greater than 1.
|
||||||
|
value_bits = 9
|
||||||
|
total_records_to_select = 8
|
||||||
|
|
||||||
|
def extract(bitpacked: int) -> Tuple[int, int]:
|
||||||
|
count = bitpacked >> value_bits
|
||||||
|
value = bitpacked & ((1 << value_bits) - 1)
|
||||||
|
return (count if count else 1), value
|
||||||
|
|
||||||
|
def pack(count: int, value: int) -> int:
|
||||||
|
return (count << value_bits) | value
|
||||||
|
|
||||||
|
either = {a, b}
|
||||||
|
# If we're building our state in the first slot, handle it
|
||||||
|
if any(x > 1 for x in either):
|
||||||
|
# Unpack the state from each input
|
||||||
|
# State is just how many records have been included so far, and the
|
||||||
|
# value which has been built
|
||||||
|
ac, av = extract(a)
|
||||||
|
bc, bv = extract(b)
|
||||||
|
count, value = ac + bc, av | bv
|
||||||
|
# If we haven't inluded eight records yet, just build up the number
|
||||||
|
if count < total_records_to_select:
|
||||||
|
return pack(count, value)
|
||||||
|
# If we've included eight records, we're done and need to check the
|
||||||
|
# value is what we wanted
|
||||||
|
# The x's represent free choices.
|
||||||
|
# 0bxxxxxxx00
|
||||||
|
secret = 0b010110100
|
||||||
|
return 3 if value == secret else 0
|
||||||
|
|
||||||
|
# Otherwise, we're just checking that we select at least one truthy value
|
||||||
|
return a | b
|
153
double_decker_train_problem.py
Normal file
153
double_decker_train_problem.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
"""
|
||||||
|
Double decker train problem:
|
||||||
|
|
||||||
|
|^^^^^^^^^^^^^^| |^^^^^^^^^^^^^^|
|
||||||
|
| Double cargo | | wagon |
|
||||||
|
~~~~ ____ |--------------| |--------------|
|
||||||
|
Y_,___|[]| | Double | | cargo wagon |
|
||||||
|
{|_|_|_|PU|_,_|______________|_,_|______________|
|
||||||
|
//oo---OO=OO O-O O-O ^ O-O O-O ^
|
||||||
|
|
||||||
|
This is a deceptively simple programming puzzle where you get to make an ordering of rail wagons.
|
||||||
|
Each wagon has two floors and there is text on the outside of the top and bottom floor.
|
||||||
|
When your chosen wagons are linked together, the whole text on the top should match the whole bottom.
|
||||||
|
Output an empty list only when there is no non-empty choice of wagons with matching text.
|
||||||
|
Your ordering may include any wagon any number of times.
|
||||||
|
|
||||||
|
Example: (illustrated above)
|
||||||
|
Input wagons: [("Double cargo ", "Double "), ("wagon", "cargo wagon")]
|
||||||
|
Output ordering: [0, 1]
|
||||||
|
|
||||||
|
Explanation:
|
||||||
|
Both the top and bottom will read "Double cargo wagon" when concatenated.
|
||||||
|
Note that there is no need to mutate whitespace characters in the input.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Callable, List, Optional, Tuple
|
||||||
|
|
||||||
|
Wagon = Tuple[str, str]
|
||||||
|
|
||||||
|
|
||||||
|
MAX_LENGTH = 10
|
||||||
|
|
||||||
|
def my_solver(wagons: List[Wagon]) -> List[int]:
|
||||||
|
# Handle empty wagon case
|
||||||
|
for i, wagon in enumerate(wagons):
|
||||||
|
if wagon[0] + wagon[1] == "":
|
||||||
|
return [i]
|
||||||
|
return solve("", "", [], prepare(wagons))
|
||||||
|
|
||||||
|
def prepare(wagons: List[Wagon]) -> List[Tuple[int, Wagon]]:
|
||||||
|
seen = set()
|
||||||
|
prepared = []
|
||||||
|
for i, wagon in enumerate(wagons):
|
||||||
|
if wagon in seen:
|
||||||
|
continue
|
||||||
|
prepared.append((i, wagon))
|
||||||
|
seen.add(wagon)
|
||||||
|
return prepared
|
||||||
|
|
||||||
|
def solve(top_text: str, bottom_text: str, ordering: List[int], wagons: List[Tuple[int, Wagon]]) -> List[int]:
|
||||||
|
if len(top_text) == 0 and len(bottom_text) == 0 and len(ordering) > 0:
|
||||||
|
return ordering
|
||||||
|
if len(ordering) > MAX_LENGTH:
|
||||||
|
return []
|
||||||
|
|
||||||
|
for z, (i, wagon) in enumerate(wagons):
|
||||||
|
top = top_text + wagon[0]
|
||||||
|
bottom = bottom_text + wagon[1]
|
||||||
|
reordered = wagons[:z] + wagons[z+1:] + [(i, wagon)]
|
||||||
|
if top.startswith(bottom):
|
||||||
|
solution = solve(top[len(bottom):], "", [*ordering, i], reordered)
|
||||||
|
if len(solution) > 0:
|
||||||
|
return solution
|
||||||
|
if bottom.startswith(top):
|
||||||
|
solution = solve("", bottom[len(top):], [*ordering, i], reordered)
|
||||||
|
if len(solution) > 0:
|
||||||
|
return solution
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def check_ordering(wagons: List[Wagon], ordering: List[int]) -> bool:
|
||||||
|
"""Checks if the text on top matches the text on the bottom"""
|
||||||
|
sentence0 = ""
|
||||||
|
sentence1 = ""
|
||||||
|
for i in ordering:
|
||||||
|
assert 0 <= i < len(wagons), f"wagon index out of range: {i}"
|
||||||
|
sentence0 += wagons[i][0]
|
||||||
|
sentence1 += wagons[i][1]
|
||||||
|
return sentence0 == sentence1
|
||||||
|
|
||||||
|
|
||||||
|
def run_test_case(
|
||||||
|
wagons: List[Wagon],
|
||||||
|
example_ordering: List[int],
|
||||||
|
ordering: List[int],
|
||||||
|
) -> str:
|
||||||
|
if ordering == []:
|
||||||
|
if example_ordering == []:
|
||||||
|
return "PASS"
|
||||||
|
return "You falsely claimed it was impossible."
|
||||||
|
|
||||||
|
if check_ordering(wagons, ordering):
|
||||||
|
if example_ordering == []:
|
||||||
|
return "PASS (and the problem setter is a dummy)"
|
||||||
|
return "PASS"
|
||||||
|
|
||||||
|
sentence0 = ""
|
||||||
|
sentence1 = ""
|
||||||
|
for i in ordering:
|
||||||
|
assert 0 <= i < len(wagons), f"wagon index out of range: {i}"
|
||||||
|
sentence0 += wagons[i][0]
|
||||||
|
sentence1 += wagons[i][1]
|
||||||
|
|
||||||
|
# return f"Your selected wagons had different sentences on the top and bottom.\n{ordering}\n{sentence0!r}\n{sentence1!r}"
|
||||||
|
|
||||||
|
return "Your selected wagons had different sentences on the top and bottom."
|
||||||
|
|
||||||
|
|
||||||
|
def run_test_cases(solver: Callable[[List[Wagon]], List[int]]):
|
||||||
|
test_cases: Tuple[List[Wagon], List[int]] = [
|
||||||
|
([("Double cargo ", "Double "), ("wagon", "cargo wagon")], [0, 1]),
|
||||||
|
([("wagon", "cargo wagon"), ("Double cargo ", "Double ")], [1, 0]),
|
||||||
|
([("Hello ", "Hello"), ("World", " World")], [0, 1]),
|
||||||
|
([("", "")], [0]),
|
||||||
|
([(".", "-.."), (".-", ".."), ("--.", "--")], [2, 1, 2, 0]),
|
||||||
|
([("bc", "ca"), ("a", "ab"), ("ca", "a"), ("abc", "c")], [1, 0, 1, 3]),
|
||||||
|
([("yy", "y"), ("xy", "yx"), ("z", "yz")], [0, 1, 1, 1, 1, 1, 2]),
|
||||||
|
([("", "42"), ("42", "")], [1, 0]),
|
||||||
|
([("aaaa", ""), ("", "a")], [0, 1, 1, 1, 1]),
|
||||||
|
([], []),
|
||||||
|
([("0", "1")], []),
|
||||||
|
([("0", "1"), (" ", " ")], []),
|
||||||
|
([("", " ")], []),
|
||||||
|
([("aa", "a"), ("aa", "a"), ("b", "ab")], [0, 2]),
|
||||||
|
([("aa", ""), ("ab", ""), ("", "aa")], [0, 2]),
|
||||||
|
([("aa", ""), ("ab", "")], []),
|
||||||
|
([("ab", "a"), ("ab", "b")], []),
|
||||||
|
([("aaaa", ""), ("", "a")], [0, 1, 1, 1, 1]),
|
||||||
|
([("ab"*1000, ""), ("a", "ab"), ("b", "ab")], [0] + [1,2]*1000),
|
||||||
|
([("a"*(2**4*3**5), ""), ("", "aa"), ("", "aaa")], [0]+[1]*2**4 +[2]*3**5),
|
||||||
|
|
||||||
|
# ([("ab", "a"), ("ab", "b")], []),
|
||||||
|
# TODO: add more test cases
|
||||||
|
]
|
||||||
|
for i, (wagons, example_ordering) in enumerate(test_cases):
|
||||||
|
print(f"Test case {i:>2}: ", end="")
|
||||||
|
if not check_ordering(wagons, example_ordering):
|
||||||
|
sentence0 = ""
|
||||||
|
sentence1 = ""
|
||||||
|
for i in example_ordering:
|
||||||
|
assert 0 <= i < len(wagons), f"wagon index out of range: {i}"
|
||||||
|
sentence0 += wagons[i][0]
|
||||||
|
sentence1 += wagons[i][1]
|
||||||
|
print(sentence0)
|
||||||
|
print(sentence1)
|
||||||
|
|
||||||
|
|
||||||
|
assert check_ordering(wagons, example_ordering), "example is invalid, dummy."
|
||||||
|
|
||||||
|
print(run_test_case(wagons, example_ordering, solver(wagons)))
|
||||||
|
|
||||||
|
|
||||||
|
run_test_cases(my_solver)
|
32
factorio nuclear power calculation.py
Normal file
32
factorio nuclear power calculation.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
mega = 1000000
|
||||||
|
giga = mega * 1000
|
||||||
|
steam_joules = 5.8 * mega / 60
|
||||||
|
|
||||||
|
|
||||||
|
# print(steam_joulesw)
|
||||||
|
|
||||||
|
# target_power = d * giga / 120
|
||||||
|
target_power = 2.28 * giga
|
||||||
|
print(target_power)
|
||||||
|
|
||||||
|
turbine_power = 5.82*mega
|
||||||
|
turbine_count = target_power / turbine_power
|
||||||
|
print('number of turbines', turbine_count)
|
||||||
|
|
||||||
|
duration = 120
|
||||||
|
turbine_steam_per_second = 60
|
||||||
|
|
||||||
|
steam_required = turbine_count * duration * turbine_steam_per_second
|
||||||
|
steam_tanks = steam_required / 25000
|
||||||
|
steam_tanks = 12*12
|
||||||
|
print('steam_tanks', steam_tanks)
|
||||||
|
|
||||||
|
|
||||||
|
tanks_in_row = 6
|
||||||
|
row_count = steam_tanks / tanks_in_row
|
||||||
|
turbines_per_row = turbine_count / row_count
|
||||||
|
|
||||||
|
print(f'row_count: {row_count}')
|
||||||
|
print(f'turbines_per_row: {turbines_per_row}')
|
||||||
|
|
||||||
|
print(25*6)
|
0
factorio nuclear power calculation.txt
Normal file
0
factorio nuclear power calculation.txt
Normal file
38
generators_example.py
Normal file
38
generators_example.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def my_context_manager():
|
||||||
|
print("begin")
|
||||||
|
yield "middle"
|
||||||
|
print("end")
|
||||||
|
|
||||||
|
|
||||||
|
with my_context_manager() as f:
|
||||||
|
print(f)
|
||||||
|
|
||||||
|
|
||||||
|
# from typing import Iterator
|
||||||
|
|
||||||
|
# # deeply_nested = [[[1, 2, 3], [4, 5]], [[6, 7], [8, 9]]]
|
||||||
|
|
||||||
|
|
||||||
|
# # def flatten(deeply_nested: list) -> Iterator[int]:
|
||||||
|
# # for a in deeply_nested:
|
||||||
|
# # for b in a:
|
||||||
|
# # for c in b:
|
||||||
|
# # yield c
|
||||||
|
# # print("here")
|
||||||
|
|
||||||
|
|
||||||
|
# # for inner in flatten(deeply_nested):
|
||||||
|
# # print(inner)
|
||||||
|
|
||||||
|
|
||||||
|
# def infinite(private_key):
|
||||||
|
# while True:
|
||||||
|
# yield from private_key
|
||||||
|
|
||||||
|
|
||||||
|
# for private_key_char, plaintext_char in zip(infinite("hello"), "my plaintext"):
|
||||||
|
# print("combine", private_key_char, plaintext_char)
|
1
heartbound OCR
Submodule
1
heartbound OCR
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 5ed08772af63910da82395c5e1912556473f3bbe
|
55
klimpen_function_chaining.py
Normal file
55
klimpen_function_chaining.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
def func(datalist, b=False):
|
||||||
|
output = []
|
||||||
|
for data in datalist:
|
||||||
|
data_a = funcA(data)
|
||||||
|
data_b = funcB(data_a) if b else data_a
|
||||||
|
data_c = funcC(data_b) if data.c else data_b
|
||||||
|
data_d = funcD(data_c)
|
||||||
|
output.append(data_d)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def func_dom_simple(datalist, want_b=False):
|
||||||
|
out = []
|
||||||
|
for data in datalist:
|
||||||
|
want_c = data.c
|
||||||
|
data = funcA(data)
|
||||||
|
if want_b:
|
||||||
|
data = funcB(data)
|
||||||
|
if want_c:
|
||||||
|
data = funcC(data)
|
||||||
|
data = funcD(data)
|
||||||
|
out.append(data)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def compose(*functions):
|
||||||
|
return lambda start: reduce(lambda f, x: f(x), functions, start)
|
||||||
|
|
||||||
|
|
||||||
|
def identity(x):
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
def func_very_haskell(datalist, want_b=False):
|
||||||
|
return map(
|
||||||
|
lambda data: compose(
|
||||||
|
funcA,
|
||||||
|
funcB if b else identity,
|
||||||
|
funcC if data.c else identity,
|
||||||
|
funcD,
|
||||||
|
)(data),
|
||||||
|
datalist,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def func_very_haskell2(datalist, want_b=False):
|
||||||
|
funcAB = compose(funcA, *([funcB] if b else []))
|
||||||
|
return map(
|
||||||
|
lambda data: compose(
|
||||||
|
funcAB,
|
||||||
|
funcC if data.c else identity,
|
||||||
|
funcD,
|
||||||
|
)(data),
|
||||||
|
datalist,
|
||||||
|
)
|
163
light_horn.py
Normal file
163
light_horn.py
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
import pyqtgraph as pg
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from PyQt6.QtCore import Qt
|
||||||
|
from PyQt6.QtWidgets import QApplication, QHBoxLayout, QLabel, QSizePolicy, QSlider, QSpacerItem, \
|
||||||
|
QVBoxLayout, QWidget
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Slider(QWidget):
|
||||||
|
def __init__(self, minimum, maximum, parent=None):
|
||||||
|
super(Slider, self).__init__(parent=parent)
|
||||||
|
self.verticalLayout = QVBoxLayout(self)
|
||||||
|
self.label = QLabel(self)
|
||||||
|
self.verticalLayout.addWidget(self.label)
|
||||||
|
self.horizontalLayout = QHBoxLayout()
|
||||||
|
spacerItem = QSpacerItem(0, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
||||||
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
|
self.slider = QSlider(self)
|
||||||
|
self.slider.setOrientation(Qt.Orientation.Vertical)
|
||||||
|
self.horizontalLayout.addWidget(self.slider)
|
||||||
|
spacerItem1 = QSpacerItem(0, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
||||||
|
self.horizontalLayout.addItem(spacerItem1)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
|
self.resize(self.sizeHint())
|
||||||
|
|
||||||
|
self.minimum = minimum
|
||||||
|
self.maximum = maximum
|
||||||
|
self.slider.valueChanged.connect(self._setLabelValue)
|
||||||
|
self.x = None
|
||||||
|
self._setLabelValue(self.slider.value())
|
||||||
|
|
||||||
|
def setValue(self, value : float):
|
||||||
|
self.slider.setValue(100 * (value - self.minimum) / (self.maximum - self.minimum))
|
||||||
|
# self.slider.setValue(value)
|
||||||
|
self._setLabelValue(self.slider.value())
|
||||||
|
|
||||||
|
|
||||||
|
def _setLabelValue(self, value):
|
||||||
|
self.x = self.minimum + (float(value) / (self.slider.maximum() - self.slider.minimum())) * (
|
||||||
|
self.maximum - self.minimum)
|
||||||
|
self.label.setText("{0:.4g}".format(self.x))
|
||||||
|
|
||||||
|
|
||||||
|
class Widget(QWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super(Widget, self).__init__(parent=parent)
|
||||||
|
self.horizontalLayout = QHBoxLayout(self)
|
||||||
|
self.w1 = Slider(0, 1)
|
||||||
|
self.w1.setValue(.4141414141414141414141414141)
|
||||||
|
# self.w1.setValue(50)
|
||||||
|
self.horizontalLayout.addWidget(self.w1)
|
||||||
|
|
||||||
|
self.w2 = Slider(-1, 1)
|
||||||
|
self.horizontalLayout.addWidget(self.w2)
|
||||||
|
|
||||||
|
self.w3 = Slider(-10, 10)
|
||||||
|
self.horizontalLayout.addWidget(self.w3)
|
||||||
|
|
||||||
|
self.w4 = Slider(-10, 10)
|
||||||
|
self.horizontalLayout.addWidget(self.w4)
|
||||||
|
|
||||||
|
self.win = pg.GraphicsWindow(title="Basic plotting examples")
|
||||||
|
self.horizontalLayout.addWidget(self.win)
|
||||||
|
self.p6 = self.win.addPlot(title="My Plot")
|
||||||
|
self.p6.setAspectLocked()
|
||||||
|
self.horn_upper = self.p6.plot(pen='r')
|
||||||
|
self.horn_lower = self.p6.plot(pen='r')
|
||||||
|
self.bounce_path = self.p6.plot(pen='w')
|
||||||
|
self.update_plot()
|
||||||
|
|
||||||
|
self.w1.slider.valueChanged.connect(self.update_plot)
|
||||||
|
self.w2.slider.valueChanged.connect(self.update_plot)
|
||||||
|
self.w3.slider.valueChanged.connect(self.update_plot)
|
||||||
|
self.w4.slider.valueChanged.connect(self.update_plot)
|
||||||
|
|
||||||
|
def update_plot(self):
|
||||||
|
|
||||||
|
k = self.w1.x
|
||||||
|
def ii(x):
|
||||||
|
return np.floor(2**x + .5)
|
||||||
|
def qq(x):
|
||||||
|
return ii(x)*x
|
||||||
|
def horn(x):
|
||||||
|
return -k *qq(x-np.log2(ii(x)))/ii(x) + 1
|
||||||
|
return np.exp(-k*x)
|
||||||
|
def horn_bot(x):
|
||||||
|
return -horn(x)
|
||||||
|
|
||||||
|
#create numpy arrays
|
||||||
|
#make the numbers large to show that the range shows data from 10000 to all the way 0
|
||||||
|
xs = np.linspace(-.5,10, 10000)
|
||||||
|
horn_upper = horn(xs)
|
||||||
|
horn_lower = -horn_upper
|
||||||
|
|
||||||
|
vel = np.array([1,0])
|
||||||
|
bounce_points = [np.array([xs[0], 1])]
|
||||||
|
def ray(t: float):
|
||||||
|
return bounce_points[-1] + t*vel
|
||||||
|
|
||||||
|
epsilon = 1e-10
|
||||||
|
|
||||||
|
# simulate bounces
|
||||||
|
for bounce_i in range(100):
|
||||||
|
bot_t = 0
|
||||||
|
top_t = .1
|
||||||
|
t = bot_t
|
||||||
|
horn_func = horn if vel[1] >= 0 else horn_bot
|
||||||
|
|
||||||
|
p = ray(t)
|
||||||
|
initial_side = p[1] < horn_func(p[0])
|
||||||
|
t = top_t
|
||||||
|
# expand search forwards
|
||||||
|
for i in range(64):
|
||||||
|
p = ray(top_t)
|
||||||
|
side = p[1] < horn_func(p[0])
|
||||||
|
if p[0] < -.5:
|
||||||
|
break
|
||||||
|
if side == initial_side:
|
||||||
|
(bot_t, top_t) = (top_t, top_t+1.1*(top_t - bot_t))
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if side == initial_side:
|
||||||
|
# print(f'never found a crossover point at bounce_i={bounce_i}')
|
||||||
|
# bounce_points.append(p)
|
||||||
|
break
|
||||||
|
# bisect
|
||||||
|
for i in range(64):
|
||||||
|
t = (bot_t + top_t) / 2
|
||||||
|
p = ray(t)
|
||||||
|
side = p[1] < horn_func(p[0])
|
||||||
|
if side == initial_side:
|
||||||
|
bot_t = t
|
||||||
|
else:
|
||||||
|
top_t = t
|
||||||
|
if bot_t == top_t:
|
||||||
|
break
|
||||||
|
dx = 2*epsilon
|
||||||
|
dy = horn_func(p[0] + epsilon) - horn_func(p[0] - epsilon)
|
||||||
|
n = np.array([-dy, dx])
|
||||||
|
n /= np.sqrt(n.dot(n)) # normal
|
||||||
|
# reflect
|
||||||
|
vel = vel - 2*(vel.dot(n))*n
|
||||||
|
bounce_points.append(p)
|
||||||
|
# (bot_t, top_t)
|
||||||
|
|
||||||
|
bounce_xs = [p[0] for p in bounce_points]
|
||||||
|
bounce_ys = [p[1] for p in bounce_points]
|
||||||
|
|
||||||
|
self.horn_upper.setData(x=xs, y=horn_upper)
|
||||||
|
self.horn_lower.setData(x=xs, y=horn_lower)
|
||||||
|
self.bounce_path.setData(x=bounce_xs, y=bounce_ys)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
w = Widget()
|
||||||
|
w.show()
|
||||||
|
sys.exit(app.exec())
|
||||||
|
|
||||||
|
# if __name__ == '__main__':
|
||||||
|
# pg.exec()
|
7
print_shelf.py
Normal file
7
print_shelf.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import shelve
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
with shelve.open(sys.argv[-1]) as shelf:
|
||||||
|
for k, v in sorted(shelf.items(), key=lambda tup: (tup[1], tup[0])):
|
||||||
|
print(k, v)
|
53
puzzle.py
Normal file
53
puzzle.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from collections import deque
|
||||||
|
|
||||||
|
initial = ". . . "
|
||||||
|
|
||||||
|
transitions = [
|
||||||
|
'S SSS ',
|
||||||
|
' SS S ',
|
||||||
|
' S S ',
|
||||||
|
'S SSS ',
|
||||||
|
'S S S',
|
||||||
|
' S S ',
|
||||||
|
' S SS',
|
||||||
|
'S S S',
|
||||||
|
]
|
||||||
|
|
||||||
|
def toggle(c: str) -> str:
|
||||||
|
return ' ' if c == '.' else '.'
|
||||||
|
|
||||||
|
def apply(state: str, transition: str) -> str:
|
||||||
|
return ''.join(toggle(c) if t=='S' else c for c, t in zip(state, transition))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print(apply(initial, transitions[0]))
|
||||||
|
|
||||||
|
def bfs(start, neighbours_fn, is_finished):
|
||||||
|
source = {start: None}
|
||||||
|
q = deque([start])
|
||||||
|
while q:
|
||||||
|
s = q.popleft()
|
||||||
|
if is_finished(s):
|
||||||
|
steps = [s]
|
||||||
|
parent = source[s]
|
||||||
|
while parent is not None:
|
||||||
|
steps.append(parent)
|
||||||
|
parent = source[parent]
|
||||||
|
steps = steps[::-1]
|
||||||
|
for i in range(len(steps)-1):
|
||||||
|
steps[i] = steps[i] + f' {neighbours_fn(steps[i]).index(steps[i+1])}'
|
||||||
|
return steps
|
||||||
|
for neigh in neighbours_fn(s):
|
||||||
|
if neigh in source:
|
||||||
|
continue
|
||||||
|
source[neigh] = s
|
||||||
|
q.append(neigh)
|
||||||
|
raise ValueError('impossible')
|
||||||
|
|
||||||
|
print('\n'.join(bfs(
|
||||||
|
initial,
|
||||||
|
lambda s: [apply(s, t) for t in transitions],
|
||||||
|
lambda s: s==' '
|
||||||
|
# lambda s: s==' . '
|
||||||
|
)))
|
1
signals
Submodule
1
signals
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 171c1fae662b711a75f0df8be7a3da3db9aa95b3
|
@ -1,3 +1,4 @@
|
|||||||
|
from math import sqrt
|
||||||
import shelve
|
import shelve
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from dataclasses import dataclass, replace
|
from dataclasses import dataclass, replace
|
||||||
@ -622,13 +623,13 @@ def shelve_it(file_name):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def get_path_from_heuristic(
|
def get_paths_from_heuristic(
|
||||||
start: Skewb, heuristic_permutation: list[int]
|
start: Skewb, heuristic_permutation: list[int]
|
||||||
) -> list[LowerAntiAxis]:
|
) -> list[list[LowerAntiAxis]]:
|
||||||
|
out: list[list[LowerAntiAxis]] = []
|
||||||
s = start
|
s = start
|
||||||
mask = [0 for _ in heuristic_permutation]
|
mask = [0 for _ in heuristic_permutation]
|
||||||
total_path_length = 0
|
total_path_length = 0
|
||||||
out: list[LowerAntiAxis] = []
|
|
||||||
for heuristic_i in heuristic_permutation:
|
for heuristic_i in heuristic_permutation:
|
||||||
mask[heuristic_i] = 1
|
mask[heuristic_i] = 1
|
||||||
|
|
||||||
@ -643,17 +644,17 @@ def get_path_from_heuristic(
|
|||||||
else:
|
else:
|
||||||
path = breadth_first_search(s, step_finished)
|
path = breadth_first_search(s, step_finished)
|
||||||
# print()
|
# print()
|
||||||
# print(f"{mask=} {s=} {path=}")
|
print(f"{mask=} {s=} {path=}")
|
||||||
if path is None:
|
if path is None:
|
||||||
raise ValueError("oh no! solver could not find solution")
|
raise ValueError("oh no! solver could not find solution")
|
||||||
out.extend(path)
|
out.append(path)
|
||||||
s = apply_twists(s, path)
|
s = apply_twists(s, path)
|
||||||
total_path_length += len(path)
|
total_path_length += len(path)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def get_total_path_length(start: Skewb, heuristic_permutation: list[int]) -> int:
|
# def get_total_path_length(start: Skewb, heuristic_permutation: list[int]) -> int:
|
||||||
return len(get_path_from_heuristic(start, heuristic_permutation))
|
# return sum(len(p) for p in get_paths_from_heuristic(start, heuristic_permutation))
|
||||||
|
|
||||||
|
|
||||||
# close_to_wrongly_solved = Skewb(top=(R0, B0, O0, G0), bot=(B0, O0, G0, R0), mids=(BY, GRB, ORG, RY, YY))
|
# close_to_wrongly_solved = Skewb(top=(R0, B0, O0, G0), bot=(B0, O0, G0, R0), mids=(BY, GRB, ORG, RY, YY))
|
||||||
@ -664,13 +665,27 @@ start = near_end
|
|||||||
HURISTIC_PERMUTATION_LENGTH = 4 + 4 + 5
|
HURISTIC_PERMUTATION_LENGTH = 4 + 4 + 5
|
||||||
|
|
||||||
|
|
||||||
|
def quadratic_mean(values: list[float]) -> float:
|
||||||
|
return sqrt(sum(x * x for x in values) / len(values))
|
||||||
|
|
||||||
|
|
||||||
|
def get_mean_path_length(
|
||||||
|
start: Skewb,
|
||||||
|
heuristic_permutation: list[int],
|
||||||
|
mean_fn: Callable[[list[float]], float] = quadratic_mean,
|
||||||
|
) -> float:
|
||||||
|
return mean_fn(
|
||||||
|
[len(p) for p in get_paths_from_heuristic(start, heuristic_permutation)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@shelve_it("skewb_solver.evaluate_permutation.shelve.sqlite")
|
@shelve_it("skewb_solver.evaluate_permutation.shelve.sqlite")
|
||||||
def evaluate_permutation(
|
def evaluate_permutation(
|
||||||
heuristic_permutation: list[int], seed=4, sample_size: int = 10
|
heuristic_permutation: list[int], seed=4, sample_size: int = 10
|
||||||
) -> float:
|
) -> float:
|
||||||
pls = []
|
pls = []
|
||||||
for i in range(sample_size):
|
for i in range(sample_size):
|
||||||
pl = get_total_path_length(random_skewb(seed=i + seed), heuristic_permutation)
|
pl = get_mean_path_length(random_skewb(seed=i + seed), heuristic_permutation)
|
||||||
print(f"{pl=}")
|
print(f"{pl=}")
|
||||||
pls.append(pl)
|
pls.append(pl)
|
||||||
return sum(pls) / len(pls)
|
return sum(pls) / len(pls)
|
||||||
@ -727,7 +742,7 @@ if __name__ == "__main__":
|
|||||||
# print(f"{hp=} {evaluate_permutation(hp, seed=200, sample_size=200)=}")
|
# print(f"{hp=} {evaluate_permutation(hp, seed=200, sample_size=200)=}")
|
||||||
|
|
||||||
hp = [10, 0, 1, 2, 3, 8, 9, 11, 12, 4, 5, 6, 7]
|
hp = [10, 0, 1, 2, 3, 8, 9, 11, 12, 4, 5, 6, 7]
|
||||||
path = get_path_from_heuristic(
|
path = get_paths_from_heuristic(
|
||||||
Skewb(top=(O0, B0, R0, G0), bot=(B2, R0, G1, O0), mids=(BY, YY, GY, RY, ORB)),
|
Skewb(top=(O0, B0, R0, G0), bot=(B2, R0, G1, O0), mids=(BY, YY, GY, RY, ORB)),
|
||||||
hp,
|
hp,
|
||||||
)
|
)
|
||||||
|
180
starchild_teaching.py
Normal file
180
starchild_teaching.py
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
from typing import List, Set, Dict, Tuple
|
||||||
|
|
||||||
|
# a: int = 2
|
||||||
|
# b: float = 2.3
|
||||||
|
# c: str = "lkasldkjaslkjdasd"
|
||||||
|
# cc: bytes = b"AAA"
|
||||||
|
# d: None = None
|
||||||
|
# e: bool = True
|
||||||
|
# f: bool = False
|
||||||
|
# k: Tuple[int, str, str] = (1, "hello", "world")
|
||||||
|
|
||||||
|
# g: List[int] = [7]
|
||||||
|
# j: Set[str] = {"friend a", "friend b"}
|
||||||
|
# i: Dict[str, int] = {"4": 6, "6": 8}
|
||||||
|
|
||||||
|
# import collections
|
||||||
|
|
||||||
|
# print(dir(collections))
|
||||||
|
|
||||||
|
# i["5"] = 7
|
||||||
|
# print(dict[str])
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Card:
|
||||||
|
suit: str
|
||||||
|
rank: int # 1 -> ace, 10+ -> jack, queen, king
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
if self.rank == 1:
|
||||||
|
rank_str = "ace"
|
||||||
|
elif self.rank == 10:
|
||||||
|
rank_str = "jack"
|
||||||
|
elif self.rank == 11:
|
||||||
|
rank_str = "queen"
|
||||||
|
elif self.rank == 12:
|
||||||
|
rank_str = "king"
|
||||||
|
else:
|
||||||
|
rank_str = str(self.rank)
|
||||||
|
return f"{rank_str} of {self.suit}"
|
||||||
|
|
||||||
|
# def __lt__(self, other) -> bool:
|
||||||
|
# if self.suit != other.suit:
|
||||||
|
# return self.suit < other.suit
|
||||||
|
# else:
|
||||||
|
# return self.rank < other.rank
|
||||||
|
|
||||||
|
|
||||||
|
hand: List[Card] = [
|
||||||
|
Card(suit="clubs", rank=6),
|
||||||
|
Card(suit="clubs", rank=5),
|
||||||
|
Card(suit="spades", rank=1),
|
||||||
|
Card(suit="hearts", rank=10),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def suit_first(card: Card) -> Tuple:
|
||||||
|
return (card.suit, card.rank)
|
||||||
|
|
||||||
|
|
||||||
|
def rank_first(card: Card) -> Tuple:
|
||||||
|
return (card.rank, card.suit)
|
||||||
|
|
||||||
|
|
||||||
|
# hand.sort(key=suit_first)
|
||||||
|
# hand.sort(key=rank_first)
|
||||||
|
# print(hand)
|
||||||
|
|
||||||
|
print((1, "clubs", "cinnamon") < (1, "clubs", "vanilla"))
|
||||||
|
|
||||||
|
# O(N ^ 2)
|
||||||
|
|
||||||
|
|
||||||
|
# for i in range(10):
|
||||||
|
# print(i)
|
||||||
|
|
||||||
|
# iterable = range(4)
|
||||||
|
# iterator = iter(iterable)
|
||||||
|
# # print(dir(iterator))
|
||||||
|
# # print(iterator.__str__()[0])
|
||||||
|
# # print(iterator)
|
||||||
|
|
||||||
|
# # print(dir(iterator.__next__))
|
||||||
|
# print(next.__doc__)
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# while True:
|
||||||
|
# print(iterator.__next__())
|
||||||
|
|
||||||
|
# except StopIteration:
|
||||||
|
# print("handled!")
|
||||||
|
|
||||||
|
[
|
||||||
|
"__class__",
|
||||||
|
"__delattr__",
|
||||||
|
"__dir__",
|
||||||
|
"__doc__",
|
||||||
|
"__eq__",
|
||||||
|
"__format__",
|
||||||
|
"__ge__",
|
||||||
|
"__getattribute__",
|
||||||
|
"__gt__",
|
||||||
|
"__hash__",
|
||||||
|
"__init__",
|
||||||
|
"__init_subclass__",
|
||||||
|
"__iter__",
|
||||||
|
"__le__",
|
||||||
|
"__length_hint__",
|
||||||
|
"__lt__",
|
||||||
|
"__ne__",
|
||||||
|
"__new__",
|
||||||
|
"__next__",
|
||||||
|
"__reduce__",
|
||||||
|
"__reduce_ex__",
|
||||||
|
"__repr__",
|
||||||
|
"__setattr__",
|
||||||
|
"__setstate__",
|
||||||
|
"__sizeof__",
|
||||||
|
"__str__",
|
||||||
|
"__subclasshook__",
|
||||||
|
]
|
||||||
|
|
||||||
|
# print(next(iterator))
|
||||||
|
# print(next(iterator))
|
||||||
|
# print(next(iterator))
|
||||||
|
# print(next(iterator))
|
||||||
|
# print(next(iterator))
|
||||||
|
|
||||||
|
|
||||||
|
# def sum_until(x: int) -> int:
|
||||||
|
# """computes the sum of number from 0 to x (inclusive)"""
|
||||||
|
|
||||||
|
# to_sum = list(range(x + 1))
|
||||||
|
# print(to_sum)
|
||||||
|
# s = 0
|
||||||
|
# for num in to_sum:
|
||||||
|
# s += num
|
||||||
|
# return s
|
||||||
|
|
||||||
|
|
||||||
|
# print(sum_until(3))
|
||||||
|
|
||||||
|
# from abc import ABC
|
||||||
|
# from dataclasses import dataclass
|
||||||
|
# from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
# class Animal(ABC):
|
||||||
|
# def make_noise(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
|
||||||
|
# @dataclass
|
||||||
|
# class Cat(Animal):
|
||||||
|
# name: str
|
||||||
|
|
||||||
|
# def make_noise(self):
|
||||||
|
# print("meow")
|
||||||
|
|
||||||
|
|
||||||
|
# class Lion(Cat):
|
||||||
|
# def hunt(self):
|
||||||
|
# print("nom")
|
||||||
|
|
||||||
|
|
||||||
|
# class Kitty(Cat):
|
||||||
|
# def make_noise(self):
|
||||||
|
# print("purr")
|
||||||
|
|
||||||
|
|
||||||
|
# animals: List[Animal] = [
|
||||||
|
# Kitty(name="Star Child"),
|
||||||
|
# Lion(name="Simba"),
|
||||||
|
# ]
|
||||||
|
# for animal in animals:
|
||||||
|
# animal.make_noise()
|
27
try.py
Normal file
27
try.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class Foo(int):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__()
|
||||||
|
self.q = x + 1
|
||||||
|
|
||||||
|
|
||||||
|
# print(Foo(3).q)
|
||||||
|
print(sys.getsizeof(3))
|
||||||
|
print(sys.getsizeof(Foo(3)))
|
||||||
|
|
||||||
|
# from typing import List
|
||||||
|
|
||||||
|
# def contains_321(ints: List[int]) -> bool:
|
||||||
|
# try:
|
||||||
|
# i3 = ints.index(3)
|
||||||
|
# i2 = ints[i3+1:].index(2)
|
||||||
|
# i1 = ints[i2+1:].index(1)
|
||||||
|
# return True
|
||||||
|
# except ValueError:
|
||||||
|
# return False
|
||||||
|
|
||||||
|
# print(contains_321([3,2,1]))
|
||||||
|
# print(contains_321([3,1,2,1,1]))
|
||||||
|
# print(contains_321([1,2,3]))
|
295
upload/SimpleHTTPServerWithUpload.py
Normal file
295
upload/SimpleHTTPServerWithUpload.py
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""Simple HTTP Server With Upload.
|
||||||
|
|
||||||
|
This module builds on BaseHTTPServer by implementing the standard GET
|
||||||
|
and HEAD requests in a fairly straightforward manner.
|
||||||
|
|
||||||
|
see: https://gist.github.com/UniIsland/3346170
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
__version__ = "0.1"
|
||||||
|
__all__ = ["SimpleHTTPRequestHandler"]
|
||||||
|
__author__ = "bones7456"
|
||||||
|
__home_page__ = "http://li2z.cn/"
|
||||||
|
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
import http.server
|
||||||
|
import urllib.request, urllib.parse, urllib.error
|
||||||
|
import html
|
||||||
|
import shutil
|
||||||
|
import mimetypes
|
||||||
|
import re
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
|
||||||
|
|
||||||
|
"""Simple HTTP request handler with GET/HEAD/POST commands.
|
||||||
|
|
||||||
|
This serves files from the current directory and any of its
|
||||||
|
subdirectories. The MIME type for files is determined by
|
||||||
|
calling the .guess_type() method. And can reveive file uploaded
|
||||||
|
by client.
|
||||||
|
|
||||||
|
The GET/HEAD/POST requests are identical except that the HEAD
|
||||||
|
request omits the actual contents of the file.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
server_version = "SimpleHTTPWithUpload/" + __version__
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
"""Serve a GET request."""
|
||||||
|
f = self.send_head()
|
||||||
|
if f:
|
||||||
|
self.copyfile(f, self.wfile)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def do_HEAD(self):
|
||||||
|
"""Serve a HEAD request."""
|
||||||
|
f = self.send_head()
|
||||||
|
if f:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
"""Serve a POST request."""
|
||||||
|
r, info = self.deal_post_data()
|
||||||
|
print((r, info, "by: ", self.client_address))
|
||||||
|
f = BytesIO()
|
||||||
|
f.write(b'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
|
||||||
|
f.write(b"<html>\n<title>Upload Result Page</title>\n")
|
||||||
|
f.write(b"<body>\n<h2>Upload Result Page</h2>\n")
|
||||||
|
f.write(b"<hr>\n")
|
||||||
|
if r:
|
||||||
|
f.write(b"<strong>Success:</strong>")
|
||||||
|
else:
|
||||||
|
f.write(b"<strong>Failed:</strong>")
|
||||||
|
f.write(info.encode())
|
||||||
|
f.write(("<br><a href=\"%s\">back</a>" % self.headers['referer']).encode())
|
||||||
|
f.write(b"<hr><small>Powerd By: bones7456, check new version at ")
|
||||||
|
f.write(b"<a href=\"http://li2z.cn/?s=SimpleHTTPServerWithUpload\">")
|
||||||
|
f.write(b"here</a>.</small></body>\n</html>\n")
|
||||||
|
length = f.tell()
|
||||||
|
f.seek(0)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "text/html")
|
||||||
|
self.send_header("Content-Length", str(length))
|
||||||
|
self.end_headers()
|
||||||
|
if f:
|
||||||
|
self.copyfile(f, self.wfile)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def deal_post_data(self):
|
||||||
|
content_type = self.headers['content-type']
|
||||||
|
if not content_type:
|
||||||
|
return (False, "Content-Type header doesn't contain boundary")
|
||||||
|
boundary = content_type.split("=")[1].encode()
|
||||||
|
remainbytes = int(self.headers['content-length'])
|
||||||
|
line = self.rfile.readline()
|
||||||
|
remainbytes -= len(line)
|
||||||
|
if not boundary in line:
|
||||||
|
return (False, "Content NOT begin with boundary")
|
||||||
|
line = self.rfile.readline()
|
||||||
|
remainbytes -= len(line)
|
||||||
|
fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line.decode())
|
||||||
|
if not fn:
|
||||||
|
return (False, "Can't find out file name...")
|
||||||
|
path = self.translate_path(self.path)
|
||||||
|
fn = os.path.join(path, fn[0])
|
||||||
|
line = self.rfile.readline()
|
||||||
|
remainbytes -= len(line)
|
||||||
|
line = self.rfile.readline()
|
||||||
|
remainbytes -= len(line)
|
||||||
|
try:
|
||||||
|
out = open(fn, 'wb')
|
||||||
|
except IOError:
|
||||||
|
return (False, "Can't create file to write, do you have permission to write?")
|
||||||
|
|
||||||
|
preline = self.rfile.readline()
|
||||||
|
remainbytes -= len(preline)
|
||||||
|
while remainbytes > 0:
|
||||||
|
line = self.rfile.readline()
|
||||||
|
remainbytes -= len(line)
|
||||||
|
if boundary in line:
|
||||||
|
preline = preline[0:-1]
|
||||||
|
if preline.endswith(b'\r'):
|
||||||
|
preline = preline[0:-1]
|
||||||
|
out.write(preline)
|
||||||
|
out.close()
|
||||||
|
return (True, "File '%s' upload success!" % fn)
|
||||||
|
else:
|
||||||
|
out.write(preline)
|
||||||
|
preline = line
|
||||||
|
return (False, "Unexpect Ends of data.")
|
||||||
|
|
||||||
|
def send_head(self):
|
||||||
|
"""Common code for GET and HEAD commands.
|
||||||
|
|
||||||
|
This sends the response code and MIME headers.
|
||||||
|
|
||||||
|
Return value is either a file object (which has to be copied
|
||||||
|
to the outputfile by the caller unless the command was HEAD,
|
||||||
|
and must be closed by the caller under all circumstances), or
|
||||||
|
None, in which case the caller has nothing further to do.
|
||||||
|
|
||||||
|
"""
|
||||||
|
path = self.translate_path(self.path)
|
||||||
|
f = None
|
||||||
|
if os.path.isdir(path):
|
||||||
|
if not self.path.endswith('/'):
|
||||||
|
# redirect browser - doing basically what apache does
|
||||||
|
self.send_response(301)
|
||||||
|
self.send_header("Location", self.path + "/")
|
||||||
|
self.end_headers()
|
||||||
|
return None
|
||||||
|
for index in "index.html", "index.htm":
|
||||||
|
index = os.path.join(path, index)
|
||||||
|
if os.path.exists(index):
|
||||||
|
path = index
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return self.list_directory(path)
|
||||||
|
ctype = self.guess_type(path)
|
||||||
|
try:
|
||||||
|
# Always read in binary mode. Opening files in text mode may cause
|
||||||
|
# newline translations, making the actual size of the content
|
||||||
|
# transmitted *less* than the content-length!
|
||||||
|
f = open(path, 'rb')
|
||||||
|
except IOError:
|
||||||
|
self.send_error(404, "File not found")
|
||||||
|
return None
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", ctype)
|
||||||
|
fs = os.fstat(f.fileno())
|
||||||
|
self.send_header("Content-Length", str(fs[6]))
|
||||||
|
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
|
||||||
|
self.end_headers()
|
||||||
|
return f
|
||||||
|
|
||||||
|
def list_directory(self, path):
|
||||||
|
"""Helper to produce a directory listing (absent index.html).
|
||||||
|
|
||||||
|
Return value is either a file object, or None (indicating an
|
||||||
|
error). In either case, the headers are sent, making the
|
||||||
|
interface the same as for send_head().
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
list = os.listdir(path)
|
||||||
|
except os.error:
|
||||||
|
self.send_error(404, "No permission to list directory")
|
||||||
|
return None
|
||||||
|
list.sort(key=lambda a: a.lower())
|
||||||
|
f = BytesIO()
|
||||||
|
displaypath = html.escape(urllib.parse.unquote(self.path))
|
||||||
|
f.write(b'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
|
||||||
|
f.write(("<html>\n<title>Directory listing for %s</title>\n" % displaypath).encode())
|
||||||
|
f.write(("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath).encode())
|
||||||
|
f.write(b"<hr>\n")
|
||||||
|
f.write(b"<form ENCTYPE=\"multipart/form-data\" method=\"post\">")
|
||||||
|
f.write(b"<input name=\"file\" type=\"file\"/>")
|
||||||
|
f.write(b"<input type=\"submit\" value=\"upload\"/></form>\n")
|
||||||
|
f.write(b"<hr>\n<ul>\n")
|
||||||
|
for name in list:
|
||||||
|
fullname = os.path.join(path, name)
|
||||||
|
displayname = linkname = name
|
||||||
|
# Append / for directories or @ for symbolic links
|
||||||
|
if os.path.isdir(fullname):
|
||||||
|
displayname = name + "/"
|
||||||
|
linkname = name + "/"
|
||||||
|
if os.path.islink(fullname):
|
||||||
|
displayname = name + "@"
|
||||||
|
# Note: a link to a directory displays with @ and links with /
|
||||||
|
f.write(('<li><a href="%s">%s</a>\n'
|
||||||
|
% (urllib.parse.quote(linkname), html.escape(displayname))).encode())
|
||||||
|
f.write(b"</ul>\n<hr>\n</body>\n</html>\n")
|
||||||
|
length = f.tell()
|
||||||
|
f.seek(0)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "text/html")
|
||||||
|
self.send_header("Content-Length", str(length))
|
||||||
|
self.end_headers()
|
||||||
|
return f
|
||||||
|
|
||||||
|
def translate_path(self, path):
|
||||||
|
"""Translate a /-separated PATH to the local filename syntax.
|
||||||
|
|
||||||
|
Components that mean special things to the local file system
|
||||||
|
(e.g. drive or directory names) are ignored. (XXX They should
|
||||||
|
probably be diagnosed.)
|
||||||
|
|
||||||
|
"""
|
||||||
|
# abandon query parameters
|
||||||
|
path = path.split('?',1)[0]
|
||||||
|
path = path.split('#',1)[0]
|
||||||
|
path = posixpath.normpath(urllib.parse.unquote(path))
|
||||||
|
words = path.split('/')
|
||||||
|
words = [_f for _f in words if _f]
|
||||||
|
path = os.getcwd()
|
||||||
|
for word in words:
|
||||||
|
drive, word = os.path.splitdrive(word)
|
||||||
|
head, word = os.path.split(word)
|
||||||
|
if word in (os.curdir, os.pardir): continue
|
||||||
|
path = os.path.join(path, word)
|
||||||
|
return path
|
||||||
|
|
||||||
|
def copyfile(self, source, outputfile):
|
||||||
|
"""Copy all data between two file objects.
|
||||||
|
|
||||||
|
The SOURCE argument is a file object open for reading
|
||||||
|
(or anything with a read() method) and the DESTINATION
|
||||||
|
argument is a file object open for writing (or
|
||||||
|
anything with a write() method).
|
||||||
|
|
||||||
|
The only reason for overriding this would be to change
|
||||||
|
the block size or perhaps to replace newlines by CRLF
|
||||||
|
-- note however that this the default server uses this
|
||||||
|
to copy binary data as well.
|
||||||
|
|
||||||
|
"""
|
||||||
|
shutil.copyfileobj(source, outputfile)
|
||||||
|
|
||||||
|
def guess_type(self, path):
|
||||||
|
"""Guess the type of a file.
|
||||||
|
|
||||||
|
Argument is a PATH (a filename).
|
||||||
|
|
||||||
|
Return value is a string of the form type/subtype,
|
||||||
|
usable for a MIME Content-type header.
|
||||||
|
|
||||||
|
The default implementation looks the file's extension
|
||||||
|
up in the table self.extensions_map, using application/octet-stream
|
||||||
|
as a default; however it would be permissible (if
|
||||||
|
slow) to look inside the data to make a better guess.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
base, ext = posixpath.splitext(path)
|
||||||
|
if ext in self.extensions_map:
|
||||||
|
return self.extensions_map[ext]
|
||||||
|
ext = ext.lower()
|
||||||
|
if ext in self.extensions_map:
|
||||||
|
return self.extensions_map[ext]
|
||||||
|
else:
|
||||||
|
return self.extensions_map['']
|
||||||
|
|
||||||
|
if not mimetypes.inited:
|
||||||
|
mimetypes.init() # try to read system mime.types
|
||||||
|
extensions_map = mimetypes.types_map.copy()
|
||||||
|
extensions_map.update({
|
||||||
|
'': 'application/octet-stream', # Default
|
||||||
|
'.py': 'text/plain',
|
||||||
|
'.c': 'text/plain',
|
||||||
|
'.h': 'text/plain',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def test(HandlerClass = SimpleHTTPRequestHandler,
|
||||||
|
ServerClass = http.server.HTTPServer):
|
||||||
|
http.server.test(HandlerClass, ServerClass)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test()
|
71
when_to_quit.py
Normal file
71
when_to_quit.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.Qt import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
initial_dollar = 100
|
||||||
|
|
||||||
|
factor_if_heads = 1.8
|
||||||
|
factor_if_tails = 0.5
|
||||||
|
|
||||||
|
population_size = 10000
|
||||||
|
num_tosses_visualized = 500
|
||||||
|
|
||||||
|
def want_to_play(money, toss) -> bool:
|
||||||
|
return True
|
||||||
|
if toss > 4:
|
||||||
|
return False
|
||||||
|
|
||||||
|
rng = np.random.default_rng(seed=4)
|
||||||
|
|
||||||
|
def evolve(want_to_play, money, toss):
|
||||||
|
# if money < 2:
|
||||||
|
# return 1
|
||||||
|
# if not want_to_play(money, toss):
|
||||||
|
# return money
|
||||||
|
|
||||||
|
if rng.choice([0,1]):
|
||||||
|
return money * factor_if_heads
|
||||||
|
else:
|
||||||
|
return money * factor_if_tails
|
||||||
|
|
||||||
|
population_histories = [[initial_dollar] for _ in range(population_size)]
|
||||||
|
for toss in range(num_tosses_visualized):
|
||||||
|
for hist in population_histories:
|
||||||
|
hist.append(evolve(want_to_play, hist[-1], toss))
|
||||||
|
|
||||||
|
|
||||||
|
app = pg.mkQApp("Plotting Example")
|
||||||
|
#mw = QtWidgets.QMainWindow()
|
||||||
|
#mw.resize(800,800)
|
||||||
|
|
||||||
|
win = pg.GraphicsLayoutWidget(show=True, title="Basic plotting examples")
|
||||||
|
win.resize(1000,600)
|
||||||
|
win.setWindowTitle('pyqtgraph example: Plotting')
|
||||||
|
|
||||||
|
# Enable antialiasing for prettier plots
|
||||||
|
pg.setConfigOptions(antialias=True)
|
||||||
|
|
||||||
|
p2 = win.addPlot(title="Multiple curves")
|
||||||
|
|
||||||
|
|
||||||
|
population_histories = np.array(population_histories)
|
||||||
|
# population_histories = np.log(population_histories + 1)
|
||||||
|
p2.setLogMode(False, True)
|
||||||
|
p2.plot(population_histories.mean(0), pen=(255, 0, 0))
|
||||||
|
p2.plot(np.median(population_histories, 0), pen=(0, 255, 0))
|
||||||
|
for percentile in range(0, 101):
|
||||||
|
print('percentile', percentile)
|
||||||
|
p2.plot(np.percentile(population_histories, percentile, 0), pen=(100, 10, 0))
|
||||||
|
|
||||||
|
# for hist in population_histories:
|
||||||
|
# p2.plot(hist, pen=(33,33,33))
|
||||||
|
|
||||||
|
# p2.plot(np.random.normal(size=100), pen=(255,0,0), name="Red curve")
|
||||||
|
# p2.plot(np.random.normal(size=110)+5, pen=(0,255,0), name="Green curve")
|
||||||
|
# p2.plot(np.random.normal(size=120)+10, pen=(0,0,255), name="Blue curve")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pg.exec()
|
Loading…
x
Reference in New Issue
Block a user