Compare commits

...

67 Commits

Author SHA1 Message Date
09ee33a751 idklol 2023-09-24 08:21:22 -04:00
ee9fb1955c Is it cat town? perhaps 2023-04-06 15:08:43 -04:00
41f53c34c0 Making some arduino-shaped messes 2023-01-07 18:44:31 -05:00
6c0083e094 Sudoku through the end of chapter 8 2022-11-26 16:09:32 -05:00
7f2f579241 Sudoku up through chapter 7 2022-11-26 09:42:41 -05:00
7d2ac20ce1 Beginning of sudoku chapter 7 with SDM loading 2022-11-25 15:37:57 -05:00
8f38a3b271 Sudoku up through chapter 5 2022-11-25 12:20:01 -05:00
96f5f85a27 Piston Sudoku up through 3rd chapter 2022-11-24 18:56:18 -05:00
6cf80e09b1 Piston tutorial getting started woop! 2022-11-24 18:25:07 -05:00
30ed115ed0 Moving argh to separate repo 2022-06-06 18:50:25 -04:00
8376608a1e Merge pull request 'arghing' (#1) from arghing into main
Reviewed-on: #1
2022-06-06 22:44:24 +00:00
3de96b813f Making more messes with parser config 2022-06-04 17:38:24 -04:00
a73acedc6d Minor tracing tweaks 2022-06-03 23:12:53 -04:00
92e3d6fe5b Support persistent flags 2022-05-31 08:24:58 -04:00
395006cdb8 Renaming some error list bits & testing windows-like 2022-05-29 21:12:57 -04:00
622d47071a Rename second parser attempt 2022-05-29 19:16:13 -04:00
1452d544bb Dropping previous parser attempt 2022-05-29 19:10:16 -04:00
56c6a8cf09 Handle remaining skipped cases 2022-05-29 19:04:31 -04:00
cc29386cee Use parser2 in querier tests 2022-05-27 08:22:07 -04:00
95453bf197 Retain literals that are values 2022-05-27 08:11:31 -04:00
a6526af6ff Implement value capture for last compound short flag 2022-05-25 22:34:32 -04:00
3ea30a997a Implementing value capture for short flags
and ensuring all unknown ident/stdin nodes are retained
2022-05-25 22:24:12 -04:00
03edacc8ec Implementing long flag values in parser2 2022-05-25 21:55:16 -04:00
d1ffbe25a3 Do AST better maybe? 2022-05-22 21:43:02 -04:00
dc3a40b19d Continuing the work with parser that's more like go/parser 2022-05-22 20:49:11 -04:00
f2e0de1b66 Making a mess with a parser that works more like go/parser 2022-05-22 08:47:45 -04:00
58842504c4 Minor bits while giving up (for now?) on command context 2022-05-18 22:19:53 -04:00
1080737931 Work on separate querier + cleanups 2022-05-18 20:15:31 -04:00
de6e907c60 Handle bare assignments as syntax error + NValue rework 2022-05-16 08:24:24 -04:00
9989801e62 Ensure program and commands can also receive positional arg values 2022-05-15 20:55:54 -04:00
8c280c303e Handle variable count flag values 2022-05-15 14:22:56 -04:00
b2e61cd0d2 More fun with parser and parse tree tests 2022-05-14 20:58:09 -04:00
c15bafe55d Yet more argh implementation fun 2022-05-13 20:58:55 -04:00
af7d5c6e14 Making a mess with command line parsing 2022-05-11 22:11:05 -04:00
512eddc1ab Spleling pdf gen 2022-01-30 11:29:35 -05:00
2bc9788441 Spleling 2022-01-30 11:28:41 -05:00
c52d9b9563 More silly bits with hyrule modeling/sim 2022-01-27 21:25:44 -05:00
fbb04df86d Define hyrule strategy swap rules 2022-01-27 21:03:19 -05:00
e30cbe2aca Playing with cards modeling 2022-01-25 10:13:53 -05:00
116ad347db More clarity around 3+ player rules, formatting fun 2022-01-23 11:38:37 -05:00
1493deac96 More hyrule refinements 2022-01-23 09:34:46 -05:00
a7e45b8add Clarify scoring 2022-01-22 21:37:52 -05:00
f1cc614836 Write out initial rules for "Hyrule" card game 2022-01-22 21:35:53 -05:00
a2661f4369 Bye now 2021-12-28 13:55:03 -05:00
b020618d57 Do the pixijs intro 2021-12-28 13:54:43 -05:00
d2405f75d8 Cleanup whoops 2021-12-28 09:20:09 -05:00
1d827b517b Done with the react thing 2021-11-07 10:06:01 -05:00
47d658f04f Going through the react tic-tac-toe tutorial 2021-11-07 10:05:16 -05:00
6c45a1390b RBE types aliasing 2021-10-25 09:38:08 -04:00
b25e99a632 RBE types inference 2021-10-25 09:35:14 -04:00
abd957d42f RBE types literals 2021-10-25 09:32:37 -04:00
d326a055f7 RBE types cast 2021-10-25 08:54:04 -04:00
6d6e600720 RBE more variable bindings fun 2021-10-06 19:40:31 -04:00
d2563484f9 RBE variable bindings mutability 2021-09-29 11:38:53 -04:00
eac3c2d8a6 RBE variable bindings 2021-09-29 11:35:26 -04:00
052fb87667 bleh 2021-09-13 09:21:29 -04:00
9f431fcb11 Silly stuff 2021-09-13 09:14:00 -04:00
7e6a2ea52b Update guessing game usage of rand 2021-09-12 15:12:16 -04:00
f45663f248 clean up mbox thing 2021-09-12 10:56:12 -04:00
951c3bcebe lol 2021-09-12 10:55:48 -04:00
f57429613a Clean up vim-just bits 2021-09-12 10:55:29 -04:00
7e976ccc6f shuffle shuffle 2021-09-12 10:55:12 -04:00
278ec88944 RBE custom types constants 2021-09-12 10:35:45 -04:00
f40981544c RBE custom types enum testcase linked list 2021-09-11 21:03:58 -04:00
cbcf9ce5fc RBE custom types enum c-like 2021-09-11 20:59:39 -04:00
30ef5d8c91 RBE custom types enum use 2021-09-11 20:56:43 -04:00
5d0811636f RBE custom types enum 2021-09-11 20:53:14 -04:00
98 changed files with 10325 additions and 1056 deletions

2
.gitignore vendored
View File

@@ -1,7 +1,9 @@
*.hex
*.log
*.out
*env
.dep
**/target/
/hello_world/main
/aoc*/**/input
/arduino/build-*/

View File

@@ -1,4 +1,4 @@
Copyright (C) 2020 Dan Buch
Copyright (C) 2022 Dan Buch
MIT License

View File

@@ -1,13 +0,0 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
[dev-packages]
mypy = ""
pytest = ""
[requires]
python_version = "3.9"

156
aoc2020/py/Pipfile.lock generated
View File

@@ -1,156 +0,0 @@
{
"_meta": {
"hash": {
"sha256": "ed02d1728cc686824535903ae2f5f3956ba104434c4c6e532237df55bcd69a12"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.9"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {},
"develop": {
"attrs": {
"hashes": [
"sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
"sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.3.0"
},
"iniconfig": {
"hashes": [
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
],
"version": "==1.1.1"
},
"mypy": {
"hashes": [
"sha256:0a0d102247c16ce93c97066443d11e2d36e6cc2a32d8ccc1f705268970479324",
"sha256:0d34d6b122597d48a36d6c59e35341f410d4abfa771d96d04ae2c468dd201abc",
"sha256:2170492030f6faa537647d29945786d297e4862765f0b4ac5930ff62e300d802",
"sha256:2842d4fbd1b12ab422346376aad03ff5d0805b706102e475e962370f874a5122",
"sha256:2b21ba45ad9ef2e2eb88ce4aeadd0112d0f5026418324176fd494a6824b74975",
"sha256:72060bf64f290fb629bd4a67c707a66fd88ca26e413a91384b18db3876e57ed7",
"sha256:af4e9ff1834e565f1baa74ccf7ae2564ae38c8df2a85b057af1dbbc958eb6666",
"sha256:bd03b3cf666bff8d710d633d1c56ab7facbdc204d567715cb3b9f85c6e94f669",
"sha256:c614194e01c85bb2e551c421397e49afb2872c88b5830e3554f0519f9fb1c178",
"sha256:cf4e7bf7f1214826cf7333627cb2547c0db7e3078723227820d0a2490f117a01",
"sha256:da56dedcd7cd502ccd3c5dddc656cb36113dd793ad466e894574125945653cea",
"sha256:e86bdace26c5fe9cf8cb735e7cedfe7850ad92b327ac5d797c656717d2ca66de",
"sha256:e97e9c13d67fbe524be17e4d8025d51a7dca38f90de2e462243ab8ed8a9178d1",
"sha256:eea260feb1830a627fb526d22fbb426b750d9f5a47b624e8d5e7e004359b219c"
],
"index": "pypi",
"markers": "python_version >= '3.5'",
"version": "==0.790"
},
"mypy-extensions": {
"hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
],
"version": "==0.4.3"
},
"packaging": {
"hashes": [
"sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858",
"sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.8"
},
"pluggy": {
"hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.13.1"
},
"py": {
"hashes": [
"sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
"sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.10.0"
},
"pyparsing": {
"hashes": [
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.4.7"
},
"pytest": {
"hashes": [
"sha256:1969f797a1a0dbd8ccf0fecc80262312729afea9c17f1d70ebf85c5e76c6f7c8",
"sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306"
],
"index": "pypi",
"markers": "python_version >= '3.6'",
"version": "==6.2.1"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"typed-ast": {
"hashes": [
"sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1",
"sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d",
"sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6",
"sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd",
"sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37",
"sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151",
"sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07",
"sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440",
"sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70",
"sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496",
"sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea",
"sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400",
"sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc",
"sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606",
"sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc",
"sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581",
"sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412",
"sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a",
"sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2",
"sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787",
"sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f",
"sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937",
"sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64",
"sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487",
"sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b",
"sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41",
"sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a",
"sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3",
"sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166",
"sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"
],
"version": "==1.4.2"
},
"typing-extensions": {
"hashes": [
"sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
"sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
"sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
],
"version": "==3.7.4.3"
}
}
}

View File

@@ -1,49 +0,0 @@
import sys
import typing
def main() -> int:
inputs = [int(s) for s in sys.stdin.read().split()]
for i, j in _find_2020_pairs(inputs):
print(f"pair: {i} * {j} == {i * j}")
for i, j, k in _find_2020_triplets(inputs):
print(f"triplet: {i} * {j} * {k} == {i * j * k}")
return 0
def _find_2020_pairs(
inputs: typing.List[int],
) -> typing.Generator[typing.Tuple[int, ...], None, None]:
found = []
for i, in0 in enumerate(inputs):
for j, in1 in enumerate(inputs):
if i == j:
continue
if in0 + in1 == 2020:
to_yield = tuple(sorted([in0, in1]))
if to_yield not in found:
yield to_yield
found.append(to_yield)
def _find_2020_triplets(
inputs: typing.List[int],
) -> typing.Generator[typing.Tuple[int, ...], None, None]:
found = []
for i, in0 in enumerate(inputs):
for j, in1 in enumerate(inputs):
for k, in2 in enumerate(inputs):
if i == j or i == k:
continue
if in0 + in1 + in2 == 2020:
to_yield = tuple(sorted([in0, in1, in2]))
if to_yield not in found:
yield to_yield
found.append(to_yield)
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,53 +0,0 @@
import sys
def main() -> int:
n_valid = 0
total = 0
for pol_pas in [PolicyPassword.fromstring(s) for s in sys.stdin.readlines(False)]:
if pol_pas.is_valid():
n_valid += 1
total += 1
print(f"{n_valid}/{total} valid")
return 0
class Policy:
def __init__(self, char: str, pos1: int, pos2: int):
self.char = char
self.pos1 = pos1
self.pos2 = pos2
@classmethod
def fromstring(cls, input_string) -> "Policy":
parts = [s.strip() for s in input_string.split(" ")][:2]
pos = [int(s) for s in parts[0].split("-")][:2]
return cls(parts[1], pos[0], pos[1])
def is_valid(self, password: str) -> bool:
matches = 0
for pos in (self.pos1 - 1, self.pos2 - 1):
if password[pos] == self.char:
matches += 1
return matches == 1
class PolicyPassword:
def __init__(self, policy: "Policy", password: str):
self.policy = policy
self.password = password
@classmethod
def fromstring(cls, input_string: str) -> "PolicyPassword":
parts = [s.strip() for s in input_string.split(":")][:2]
return cls(Policy.fromstring(parts[0]), parts[1])
def is_valid(self) -> bool:
return self.policy.is_valid(self.password)
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,52 +0,0 @@
import functools
import sys
import typing
class Loc(typing.NamedTuple):
x: int
y: int
def main() -> int:
forest_frame = [list(line.strip()) for line in sys.stdin.readlines()]
frame_width = len(forest_frame[0])
frame_height = len(forest_frame)
all_trees_encountered = []
for slope in [
Loc(x=1, y=1),
Loc(x=3, y=1),
Loc(x=5, y=1),
Loc(x=7, y=1),
Loc(x=1, y=2),
]:
loc = Loc(x=0, y=0)
trees_encountered = 0
while loc.y <= (frame_height - 1):
at_loc = forest_frame[loc.y][loc.x]
if at_loc == "#":
trees_encountered += 1
next_x = (loc.x + slope.x) % frame_width
next_y = loc.y + slope.y
next_loc = Loc(x=next_x, y=next_y)
loc = next_loc
print(
f"(slope right={slope.x} down={slope.y}) trees encountered: {trees_encountered}"
)
all_trees_encountered.append(trees_encountered)
trees_encountered_product = functools.reduce(
lambda x, y: x * y, all_trees_encountered
)
print(f"trees encountered product: {trees_encountered_product}")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,115 +0,0 @@
import sys
import typing
def main() -> int:
checked = []
for passport in _read_passports(sys.stdin):
if passport is None:
checked.append(False)
continue
checked.append(passport.is_valid())
print(f"total={len(checked)} valid={checked.count(True)}")
return 0
NoneString = typing.Optional[str]
VALID_EYE_COLORS = ("amb", "blu", "brn", "gry", "grn", "hzl", "oth")
class Passport:
byr: NoneString = None
cid: NoneString = None
ecl: NoneString = None
eyr: NoneString = None
hcl: NoneString = None
hgt: NoneString = None
iyr: NoneString = None
pid: NoneString = None
def is_valid(self) -> bool:
return (
self._is_year_in_range(self.byr, range(1920, 2003))
and self._is_year_in_range(self.iyr, range(2010, 2021))
and self._is_year_in_range(self.eyr, range(2020, 2031))
and self._has_valid_height()
and self._has_valid_hair_color()
and self.ecl in VALID_EYE_COLORS
and self._has_valid_passport_id()
)
def _has_valid_height(self) -> bool:
if self.hgt is None:
return False
height_value = 0
height_value_string = self.hgt.replace("cm", "").replace("in", "")
if not height_value_string.isdigit():
return False
height = int(height_value_string)
if self.hgt.endswith("cm") and height in range(150, 194):
return True
elif self.hgt.endswith("in") and height in range(59, 77):
return True
return False
def _has_valid_hair_color(self) -> bool:
if self.hcl is None:
return False
if not self.hcl.startswith("#"):
return False
hair_value = self.hcl.replace("#", "")
if len(hair_value) != 6:
return False
try:
_ = int(hair_value, 16)
return True
except ValueError:
return False
def _has_valid_passport_id(self) -> bool:
return (
self.pid is not None
and len(self.pid) == 9
and all([s.isdigit() for s in list(self.pid)])
)
def _is_year_in_range(self, value: NoneString, yr_range: range) -> bool:
if value is None:
return False
if len(value) != 4:
return False
if not value.isdigit():
return False
return int(value) in yr_range
def _read_passports(
instream: typing.TextIO,
) -> typing.Generator[typing.Optional[Passport], None, None]:
cur = Passport()
for i, line in enumerate(instream):
line = line.strip()
if line == "":
yield cur
cur = Passport()
for pair in line.split():
attr, value = pair.split(":", 1)
setattr(cur, attr, value)
yield cur
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,77 +0,0 @@
import sys
import typing
def main() -> int:
highest_seat = 0
taken_seats = set()
for line in sys.stdin:
line = line.strip()
if line == "":
continue
seat = _locate_seat(line)
if seat.number > highest_seat:
highest_seat = seat.number
taken_seats.add(seat.number)
print(f"bp={line} row={seat.row} column={seat.col} seat={seat.number}")
seat_number: typing.Optional[int] = None
n_found = 0
for candidate_seat in range(0, (127 * 8) + 1):
if candidate_seat in taken_seats:
continue
if (candidate_seat - 1) in taken_seats and (candidate_seat + 1) in taken_seats:
seat_number = candidate_seat
n_found += 1
print(f"highest_seat={highest_seat} seat_number={seat_number} n_found={n_found}")
return 0
class Seat:
row: int
column: int
def __init__(self, row: int = 0, col: int = 0):
self.row = row
self.col = col
@property
def number(self) -> int:
return (self.row * 8) + self.col
def _locate_seat(bp: str) -> Seat:
rows = list(range(0, 128))
cols = list(range(0, 8))
row_part = list(bp[:7])
col_part = list(bp[7:])
return Seat(
row=_bisect(rows, [{"F": 0, "B": 1}[s] for s in row_part]),
col=_bisect(cols, [{"L": 0, "R": 1}[s] for s in col_part]),
)
def _bisect(initial_selection: typing.List[int], bisections: typing.List[int]) -> int:
selection = initial_selection[:]
for bisection in bisections:
halfway = int(len(selection) / 2)
selection = [selection[:halfway], selection[halfway:]][bisection]
return selection[0]
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,3 +0,0 @@
BFFFBBFRRR
FFFBBBFRRR
BBFFBBFRLL

View File

@@ -1,3 +0,0 @@
bp=BFFFBBFRRR row=70 column=7 seat=567
bp=FFFBBBFRRR row=14 column=7 seat=119
bp=BBFFBBFRLL row=102 column=4 seat=820

View File

@@ -1,21 +0,0 @@
import sys
from pathlib import Path
import pytest
from solution import main
HERE = Path(__file__).absolute().parent
def test_solution(capsys):
with (HERE / "test-input").open() as infile:
sys.stdin = infile
main()
expected_output = (HERE / "test-output").read_text().splitlines()
assert expected_output == [
l for l in capsys.readouterr().out.splitlines() if l.startswith("counts_sum=")
]

View File

@@ -1,42 +0,0 @@
import sys
import typing
def main() -> int:
counts_sum = sum([c for c in _iter_group_counts(sys.stdin)])
print(f"counts_sum={counts_sum}")
return 0
def _iter_group_counts(instream: typing.TextIO) -> typing.Generator[int, None, None]:
for i, group in enumerate(_iter_groups(instream)):
answers = set(list(group[0]))
print(f"i={i} initial={answers}")
for answers_text in group[1:]:
to_add = set(list(answers_text))
answers = answers.intersection(set(list(answers_text)))
print(f"i={i} added={to_add} result={answers}")
print(f"i={i} final={answers} n={len(answers)}")
yield len(answers)
def _iter_groups(instream):
cur_group = []
for line in instream:
line = line.strip()
if line == "":
yield cur_group
cur_group = []
continue
cur_group.append(line)
yield cur_group
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,15 +0,0 @@
abc
a
b
c
ab
ac
a
a
a
a
b

View File

@@ -1 +0,0 @@
counts_sum=6

View File

@@ -1,21 +0,0 @@
import sys
from pathlib import Path
import pytest
from solution import main
HERE = Path(__file__).absolute().parent
def test_solution(capsys):
with (HERE / "test-input").open() as infile:
sys.stdin = infile
main()
expected_output = (HERE / "test-output").read_text().splitlines()
assert expected_output == [
l for l in capsys.readouterr().out.splitlines() if l.startswith("counts_sum")
]

2
arduino/.envrc Normal file
View File

@@ -0,0 +1,2 @@
export ARDMK_DIR=/usr/share/arduino
export ARDMK_VENDOR=archlinux-arduino

3
arduino/Makefile Normal file
View File

@@ -0,0 +1,3 @@
BOARD_TAG = uno
include $(ARDMK_DIR)/Arduino.mk

31
arduino/sos.ino Normal file
View File

@@ -0,0 +1,31 @@
#define DIT_DURATION_MS 88
#define LETTER_PAUSE_MS 1000
void setup() {
pinMode(13, OUTPUT);
}
void dit() {
digitalWrite(13, HIGH);
delay(DIT_DURATION_MS);
digitalWrite(13, LOW);
delay(DIT_DURATION_MS);
}
void dah() {
digitalWrite(13, HIGH);
delay(DIT_DURATION_MS * 3);
digitalWrite(13, LOW);
delay(DIT_DURATION_MS);
}
void loop() {
dit(); dit(); dit();
delay(LETTER_PAUSE_MS);
dah();
delay(LETTER_PAUSE_MS);
dit(); dit(); dit();
delay(LETTER_PAUSE_MS);
}

3
cat-town/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/node_modules/
/src/*.js
/dist/

4838
cat-town/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

30
cat-town/package.json Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "cat-town",
"version": "0.1.0",
"private": true,
"main": "index.js",
"scripts": {
"webpack": "webpack",
"dev": "webpack serve --config webpack.development.js",
"start": "npm run dev",
"build:dev": "webpack --config webpack.development.js",
"build:prod": "webpack --config webpack.production.js"
},
"devDependencies": {
"@excaliburjs/testing": "^0.25.1",
"clean-webpack-plugin": "^3.0.0",
"compression-webpack-plugin": "^7.1.2",
"html-webpack-plugin": "^5.5.0",
"source-map-loader": "^2.0.2",
"terser-webpack-plugin": "^5.3.6",
"ts-loader": "^9.4.2",
"typescript": "^4.9.4",
"webpack": "^5.75.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"excalibur": "^0.27.0"
}
}

View File

@@ -0,0 +1,17 @@
import { Actor, Color, vec } from 'excalibur'
import { Resources } from '../resources'
export class Player extends Actor {
constructor() {
super({
pos: vec(150, 150),
width: 25,
height: 25,
color: new Color(255, 100, 100)
})
}
onInitialize() {
this.graphics.use(Resources.Cat.toSprite())
}
}

16
cat-town/src/cat.ts Normal file
View File

@@ -0,0 +1,16 @@
// type Cat = {
// name string;
// years int;
// centimeters int;
// kilograms int;
// coloring Coloring;
// pattern Pattern;
// mood Mood;
// };
//
// type Coloring = 'orange' | 'black' | 'brown' | 'blue';
//
// type Pattern = 'plain' | 'striped' | 'spotted';
//
// type Mood = 'happy' | 'sad' | 'purring' |
// 'screaming' | 'mad' | 'scratchy' | 'curious' | 'concerned';

BIN
cat-town/src/images/cat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

30
cat-town/src/index.ts Normal file
View File

@@ -0,0 +1,30 @@
import { Engine, Loader, DisplayMode } from 'excalibur'
import { Beginning } from './scenes/beginning'
import { Player } from './actors/player'
import { Resources } from './resources'
class Game extends Engine {
private player: Player
private beginning: Beginning
constructor() {
super({ displayMode: DisplayMode.FitScreen })
}
public start() {
this.beginning = new Beginning()
this.player = new Player()
this.beginning.add(this.player)
game.add('beginning', this.beginning)
const loader = new Loader(Object.values(Resources))
return super.start(loader)
}
}
const game = new Game()
game.start().then(() => {
game.goToScene('beginning')
})

View File

@@ -0,0 +1,8 @@
import { ImageSource } from 'excalibur'
import catImage from './images/cat.png'
const Resources = {
Cat: new ImageSource(catImage)
}
export { Resources }

View File

@@ -0,0 +1,7 @@
import { Engine, Scene } from 'excalibur'
export class Beginning extends Scene {
public onInitialize(engine: Engine) {}
public onActivate() {}
public onDeactivate() {}
}

22
cat-town/src/town.ts Normal file
View File

@@ -0,0 +1,22 @@
// type Town = {
// grid Grid;
// };
//
// type Grid = {
// squares Map<Coords, Square>;
// };
//
// type Coords = {
// x int;
// y int;
// };
//
// type Square = {
// description string;
// things Map<string, Thing>;
// };
//
// type Thing = {
// name string;
// description string;
// };

14
cat-town/tsconfig.json Normal file
View File

@@ -0,0 +1,14 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"sourceMap": true,
"target": "es2017",
"module": "es6",
"types": ["excalibur"],
"outDir": "./dist/",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
}
}

View File

@@ -0,0 +1,47 @@
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.ts",
target: "web",
output: {
filename: '[name].js',
sourceMapFilename: "[file].map",
path: path.resolve(__dirname, "dist"),
},
devtool: "source-map",
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource"
},
{
test: /\.js$/,
use: ["source-map-loader"],
exclude: [path.resolve(__dirname, "node_modules/excalibur")],
enforce: "pre",
},
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
optimization: {
splitChunks: {
chunks: "all",
},
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebPackPlugin({
title: "Cat Town",
}),
],
};

View File

@@ -0,0 +1,12 @@
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map",
devServer: {
static: {
directory: "./dist",
},
},
});

View File

@@ -0,0 +1,13 @@
const { merge } = require("webpack-merge");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const common = require("./webpack.common");
module.exports = merge(common, {
mode: "production",
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
plugins: [new CompressionWebpackPlugin()],
});

View File

@@ -1,116 +0,0 @@
import argparse
import gzip
import hashlib
import logging
import os
import pathlib
import sys
import time
import typing
def main(sysargs=sys.argv[:]) -> int:
parser = argparse.ArgumentParser()
parser.add_argument("mbox", type=argparse.FileType("rb"))
parser.add_argument("output_directory", type=pathlib.Path)
parser.add_argument(
"-s",
"--zzz",
default=0.005,
type=float,
help="sleep seconds in between messages",
)
parser.add_argument(
"-D",
"--debug",
action="store_true",
help="increase logging verbosity to debug level",
)
args = parser.parse_args(sysargs[1:])
log_level = logging.INFO
if os.environ.get("DEBUG") == "enabled":
log_level = logging.DEBUG
logging.basicConfig(level=log_level)
MBoxExploder().explode(
mbox=args.mbox, output_directory=args.output_directory, pause_seconds=args.zzz
)
return 0
class MBoxMessage:
def __init__(self):
self.lines = []
def as_gz_bytes(self) -> bytes:
return gzip.compress(self.as_bytes())
def as_bytes(self) -> bytes:
return b"".join([l for l in self.lines])
def signature(self) -> str:
return hashlib.sha512(self.as_bytes()).hexdigest()
def relpath(self) -> str:
sig = self.signature()
return os.path.sep.join([sig[0:2], sig[2:4], sig])
def gz_relpath(self) -> str:
return self.relpath() + ".gz"
class MBoxExploder:
def __init__(self):
self._log = logging.getLogger().getChild("mbox-exploder")
def explode(
self,
mbox: typing.BinaryIO,
output_directory: pathlib.Path,
pause_seconds: float,
):
for i, msg in enumerate(self._iter_mbox(mbox)):
if len(msg.lines) < 2:
self._log.warn("skipping invalid message (%r)", i)
continue
dest = output_directory / msg.gz_relpath()
dest.parent.mkdir(parents=True, exist_ok=True)
self._log.info("writing message to %s", str(dest))
dest.write_bytes(msg.as_gz_bytes())
time.sleep(pause_seconds)
def _iter_mbox(
self, mbox: typing.BinaryIO
) -> typing.Generator[MBoxMessage, None, None]:
msg = MBoxMessage()
cur_line = b""
while True:
byte = mbox.read(1)
if len(byte) == 0:
self._log.debug("reached EOF")
msg.lines.append(cur_line)
yield msg
return
cur_line += byte
if byte != b"\n":
continue
if cur_line.startswith(b"From ") and len(msg.lines) > 1:
self._log.debug("reached new msg")
yield msg
msg = MBoxMessage()
self._log.debug("appending line %r", cur_line)
msg.lines.append(cur_line)
cur_line = b""
if __name__ == "__main__":
sys.exit(main())

178
guessing_game/Cargo.lock generated
View File

@@ -1,178 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "guessing_game"
version = "0.1.0"
dependencies = [
"rand",
]
[[package]]
name = "libc"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg",
"libc",
"rand_chacha",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg",
"rand_core 0.3.1",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

207
hyrule/README.md Normal file
View File

@@ -0,0 +1,207 @@
# Hyrule
A card game for 2-7 players.
## requirements
Use a standard card playing deck, keeping Jokers. Shuffle however
you like.
## dealing
Each player is dealt 7 cards, kept secret from other players.
## turns
There are two variations for taking turns. "Chance rules" is
strictly a matter of chance, and is recommended for impatient
players because it tends to be faster-paced and has more of a
*surprise!* element. "Strategy rules" introduces an element of
strategy and is better suited for players with more _patience_.
### chance rules
Each player selects one card and places it face down in the middle
playing area between themselves and other players.
On the count of 3, all said together in rhythm, each player flips
over their own card. Precedence applies and the winning player
takes all cards.
### strategy rules
On the first turn or when an equal number of cards have been
captured by each player, the tallest player goes first. On each
subsequent turn, the player with the most captured cards plays
first. The play order then proceeds counter-clockwise.
When taking one's turn, the player may choose to either *play* or
*swap*.
#### strategy *play*
When choosing to *play*, the player selects a card and places it
face-up in the center play area. The remaining players take turns
counter-clockwise, each placing a card face-up in the center play
area. Precedence rules apply and the winning player takes all
cards.
#### strategy *swap*
When choosing to *swap*, the player discards one card face-up in
the discard pile (next to the stock pile) and then draws a card
from the stock, which should be laying face-down. The goal here may
be to take a chance at getting a better card than one is
discarding, or to force the next player in the rotation to play, or
both.
> **NOTE**: a player may only choose to *swap* if the player on the
> previous turn _did not swap_.
## precedence
The following rules apply across suits with the exception of
*jokers and fives* (explained below). Cards within a single suit
are compared with higher-value cards winning. Cards are counted
from ace (1) through king (13).
Ways to think about these rules could include:
- "rupee buys bomb" / money buys weapon
- "rupee buys sword" / money buys weapon
- "bomb blows up sword" / range weapon beats melee weapon
- "bomb blows up heart" / range weapon beats unarmed
- "sword cuts through heart" / melee weapon beats unarmed
- "heart is stronger than rupee" / love conquers money
**NOTE:** In the case of a turn that involves 3 or more cards, the
presence of both diamonds *and* hearts will result in the
highest-value heart winning the turn.
### diamonds ("rupees")
Beats:
- clubs ("bombs")
- spades ("swords")
### clubs ("bombs")
Beats:
- spades ("swords")
- hearts
### spades ("swords")
Beats:
- hearts
### hearts
Beats:
- diamonds ("rupees")
### jokers ("tingles")
Beats everything except *fives*
### fives
The 5 of a given suit will be granted special status *only* when
played against a joker ("tingle") and will win with the following
sub-precedence, which is roughly the inverse of the main
precedence:
- 5 of hearts
- 5 of spades / "master sword"
- 5 of clubs / "bomb cluster"
- 5 of diamonds / "blue rupee"
## scoring
At the conclusion of a round of 7 cards, the player with the most
cards is the winner. The face values of the cards are not
considered at scoring time. A draw may be handled in a "run-off
game" or ignored as you like.
## examples
In the following examples, the **winning card** is highlighted at
the top of each list, followed by an explanation for the outcome.
### 2-player
- **2 of clubs**
- 2 of spades
Clubs are higher-value than spades, or "bomb beats sword".
---
- **2 of clubs**
- ace of clubs
Cards within the same suit are compared at face value with aces
being *1*.
---
- **ace of hearts**
- king of diamonds
Hearts take precedence over diamonds, or "love is stronger than
money".
---
- **joker**
- king of hearts
The opposing card is not a *five*, or "tingle takes _(thing)_".
---
- **5 of spades**
- joker
The 5 of any suit will beat a joker given its special item status
in that scenario, or "tingle is distracted by the beauty of
_(thing)_".
### 3-player
- **2 of diamonds**
- 2 of clubs
- 2 of spades
Diamonds have higher precedence than clubs and spades, and there
are no hearts present.
---
- **6 of clubs**
- 6 of spades
- 6 of hearts
Clubs have higher precedence than spades and hearts, and there are
no diamonds present.
---
- **8 of hearts**
- 8 of diamonds
- 8 of spades
When both diamonds and hearts are present, hearts is highest
precedence.
---
- **king of diamonds**
- jack of diamonds
- queen of diamonds
Within the same suit, cards are compared by face value.

BIN
hyrule/README.pdf Normal file

Binary file not shown.

86
hyrule/cards.py Normal file
View File

@@ -0,0 +1,86 @@
import dataclasses
import enum
import random
Suit = enum.Enum(
"Suit",
"""
CLUBS
DIAMONDS
HEARTS
SPADES
""",
)
FaceValue = enum.Enum(
"FaceValue",
"""
ACE
TWO
THREE
FOUR
FIVE
SIX
SEVEN
EIGHT
NINE
TEN
JACK
QUEEN
KING
""",
)
@dataclasses.dataclass
class Card:
suit: Suit
face_value: FaceValue
def __str__(self):
return f"{self.face_value} of {self.suit}"
class Joker:
def __str__(self):
return "JOKER"
class Deck:
def __init__(self, n_jokers=2):
self._cards = list(Deck.generate(n_jokers=n_jokers))
def __repr__(self):
return f"<Deck len={len(self)}>"
def __str__(self):
as_string = []
for card in self._cards:
as_string.append(str(card))
return "\n".join(as_string)
def __len__(self):
return len(self._cards)
def draw(self):
if len(self._cards) > 0:
return self._cards.pop()
return None
def shuffle(self):
random.shuffle(self._cards)
return self
def cut(self):
cut_point = random.randint(0, len(self))
self._cards = self._cards[cut_point:] + self._cards[:cut_point]
return self
@staticmethod
def generate(n_jokers=2):
for _ in range(n_jokers):
yield Joker()
for suit in Suit:
for face_value in FaceValue:
yield Card(suit=suit, face_value=face_value)

66
hyrule/hyrule.py Normal file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import argparse
import dataclasses
import pprint
import sys
import typing
import cards
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(
"--player-count", "-c", default=2, type=int, help="The number of players"
)
parser.add_argument(
"--turn-count",
"-n",
default=5,
type=int,
help="The number of turns to play",
)
args = parser.parse_args()
Hyrule(player_count=args.player_count, turn_count=args.turn_count).play()
return 0
@dataclasses.dataclass
class Player:
index: int
hand: typing.Set[cards.Card]
captured: typing.Set[cards.Card]
@property
def score(self):
return len(self.captured)
class Hyrule:
def __init__(self, player_count=2, turn_count=5):
self._players = [
Player(index=i, hand=set(), captured=set()) for i in range(player_count)
]
self._turn_count = turn_count
def play(self):
for turn in self._each_turn():
self._show_turn(turn)
def _each_turn(self):
for turn_number in range(self._turn_count):
yield self._simulate_turn(turn_number)
def _simulate_turn(self, turn_number):
...
def _show_turn(self, turn):
print(turn)
if __name__ == "__main__":
sys.exit(main())

2
hyrule/justfile Normal file
View File

@@ -0,0 +1,2 @@
build:
pandoc -r markdown -w pdf -o README.pdf README.md

1876
piston-tutorials/getting-started/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
[package]
name = "spinning-square"
version = "0.1.0"
authors = [
"Dan Buch <dan@meatballhat.com>",
"TyOverby <ty@pre-alpha.com>",
"Nikita Pekin <contact@nikitapek.in>"
]
[[bin]]
name = "spinning-square"
[dependencies]
piston = "0.53.0"
piston2d-graphics = "0.43.0"
pistoncore-glutin_window = "0.70.1"
piston2d-opengl_graphics = "0.82.0"

View File

@@ -0,0 +1,70 @@
extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventSettings, Events};
use piston::input::{RenderArgs, RenderEvent, UpdateArgs, UpdateEvent};
use piston::window::WindowSettings;
pub struct App {
gl: GlGraphics,
rotation: f64,
}
impl App {
fn render(&mut self, args: &RenderArgs) {
use graphics::*;
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
let square = rectangle::square(0.0, 0.0, 50.0);
let rotation = self.rotation;
let (x, y) = (args.window_size[0] / 2.0, args.window_size[1] / 2.0);
self.gl.draw(args.viewport(), |c, gl| {
clear(GREEN, gl);
let transform = c
.transform
.trans(x, y)
.rot_rad(rotation)
.trans(-25.0, -25.0);
rectangle(RED, square, transform, gl);
})
}
fn update(&mut self, args: &UpdateArgs) {
self.rotation += 2.0 * args.dt;
}
}
fn main() {
let opengl = OpenGL::V3_2;
let mut window: Window = WindowSettings::new("spinning-square", [200, 200])
.graphics_api(opengl)
.exit_on_esc(true)
.build()
.unwrap();
let mut app = App {
gl: GlGraphics::new(opengl),
rotation: 0.0,
};
let mut events = Events::new(EventSettings::new());
while let Some(e) = events.next(&mut window) {
if let Some(args) = e.render_args() {
app.render(&args);
}
if let Some(args) = e.update_args() {
app.update(&args);
}
}
}

1876
piston-tutorials/sudoku/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
[package]
name = "sudoku"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
piston = "0.53.2"
piston2d-graphics = "0.43.0"
piston2d-opengl_graphics = "0.82.0"
pistoncore-glutin_window = "0.70.1"

Binary file not shown.

View File

@@ -0,0 +1,99 @@
Copyright (c) 2014, Mozilla Foundation https://mozilla.org/
with Reserved Font Name Fira Sans.
Copyright (c) 2014, Mozilla Foundation https://mozilla.org/
with Reserved Font Name Fira Mono.
Copyright (c) 2014, Telefonica S.A.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@@ -0,0 +1,155 @@
//! Game board logic.
use std::fs::read_to_string;
const SIZE: usize = 9;
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Cell {
pub value: u8,
pub loaded: bool,
pub invalid: bool,
}
#[derive(Debug, PartialEq)]
pub struct Gameboard {
pub cells: [[Cell; SIZE]; SIZE],
pub completed: bool,
}
impl Gameboard {
pub fn new() -> Gameboard {
Gameboard {
cells: [[Cell::default(); SIZE]; SIZE],
completed: false,
}
}
pub fn from_cells(cells: [[u8; SIZE]; SIZE]) -> Gameboard {
let mut ret = Gameboard::new();
for (i, row) in cells.iter().enumerate() {
for (j, &col) in row.iter().enumerate() {
ret.cells[i][j] = Cell {
value: col,
loaded: col != 0,
invalid: false,
};
}
}
ret
}
pub fn char(&self, ind: [usize; 2]) -> Option<char> {
Some(match self.cells[ind[1]][ind[0]].value {
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
9 => '9',
_ => return None,
})
}
pub fn set(&mut self, ind: [usize; 2], val: u8) {
if !self.cells[ind[1]][ind[0]].loaded {
self.validate(ind, val);
self.cells[ind[1]][ind[0]].value = val;
}
self.completed = self
.cells
.iter()
.flatten()
.all(|cell| !cell.invalid && cell.value != 0);
}
pub fn load_sdm(filename: &str) -> Self {
let data = read_to_string(filename).expect("failed to read SDM file");
let mut cells = [[Cell::default(); SIZE]; SIZE];
let mut row = 0;
let mut col = 0;
for c in data.chars() {
if col == SIZE {
col = 0;
row += 1;
}
if let Some(v) = c.to_digit(10) {
let value = v as u8;
cells[row][col] = Cell {
value,
loaded: value != 0,
invalid: false,
};
col += 1;
}
}
Self {
cells,
completed: false,
}
}
fn validate(&mut self, ind: [usize; 2], val: u8) {
let [b, a] = ind;
for i in 0..SIZE {
if i == a {
continue;
}
if self.cells[a][i].value == val {
self.cells[a][b].invalid = true;
return;
}
}
for i in 0..SIZE {
if i == b {
continue;
}
if self.cells[i][b].value == val {
self.cells[a][b].invalid = true;
return;
}
}
let (row, col) = (a / 3, b / 3);
for i in 3 * row..3 * row + 3 {
for j in 3 * col..3 * col + 3 {
if i == a && j == b {
continue;
}
if self.cells[i][j].value == val {
self.cells[a][b].invalid = true;
return;
}
}
}
self.cells[a][b].invalid = false;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn load_sdm() {
let got = Gameboard::load_sdm("static/puzzle.sdm");
let want = Gameboard::from_cells([
[0, 1, 6, 4, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 9, 0, 0, 0],
[4, 0, 0, 0, 0, 0, 0, 6, 2],
[0, 7, 0, 2, 3, 0, 1, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 3],
[0, 0, 3, 0, 8, 7, 0, 4, 0],
[9, 6, 0, 0, 0, 0, 0, 0, 5],
[0, 0, 0, 8, 0, 0, 0, 0, 7],
[0, 0, 0, 0, 0, 6, 8, 2, 0],
]);
assert_eq!(got, want);
}
}

View File

@@ -0,0 +1,57 @@
//! Gameboard controller
use piston::GenericEvent;
use crate::Gameboard;
pub struct GameboardController {
pub gameboard: Gameboard,
pub selected_cell: Option<[usize; 2]>,
cursor_pos: [f64; 2],
}
impl GameboardController {
pub fn new(gameboard: Gameboard) -> GameboardController {
GameboardController {
gameboard: gameboard,
selected_cell: None,
cursor_pos: [0.0; 2],
}
}
pub fn event<E: GenericEvent>(&mut self, pos: [f64; 2], size: f64, e: &E) {
use piston::input::{Button, Key, MouseButton};
if let Some(pos) = e.mouse_cursor_args() {
self.cursor_pos = pos;
}
if let Some(Button::Mouse(MouseButton::Left)) = e.press_args() {
let x = self.cursor_pos[0] - pos[0];
let y = self.cursor_pos[1] - pos[1];
if x >= 0.0 && x < size && y >= 0.0 && y < size {
let cell_x = (x / size * 9.0) as usize;
let cell_y = (y / size * 9.0) as usize;
self.selected_cell = Some([cell_x, cell_y]);
}
}
if let Some(Button::Keyboard(key)) = e.press_args() {
if let Some(ind) = self.selected_cell {
match key {
Key::D1 => self.gameboard.set(ind, 1),
Key::D2 => self.gameboard.set(ind, 2),
Key::D3 => self.gameboard.set(ind, 3),
Key::D4 => self.gameboard.set(ind, 4),
Key::D5 => self.gameboard.set(ind, 5),
Key::D6 => self.gameboard.set(ind, 6),
Key::D7 => self.gameboard.set(ind, 7),
Key::D8 => self.gameboard.set(ind, 8),
Key::D9 => self.gameboard.set(ind, 9),
_ => {}
}
}
}
}
}

View File

@@ -0,0 +1,210 @@
//! Gameboard view.
use graphics::character::CharacterCache;
use graphics::types::Color;
use graphics::{Context, Graphics};
use crate::gameboard_controller::GameboardController;
pub struct GameboardViewSettings {
pub position: [f64; 2],
pub size: f64,
pub background_color: Color,
pub border_color: Color,
pub board_edge_color: Color,
pub section_edge_color: Color,
pub cell_edge_color: Color,
pub board_edge_radius: f64,
pub section_edge_radius: f64,
pub cell_edge_radius: f64,
pub selected_cell_background_color: Color,
pub text_color: Color,
pub loaded_cell_background_color: Color,
pub invalid_cell_background_color: Color,
pub invalid_selected_cell_background_color: Color,
pub completed_background_color: Color,
}
impl GameboardViewSettings {
pub fn new() -> GameboardViewSettings {
GameboardViewSettings {
position: [10.0; 2],
size: 400.0,
background_color: [0.8, 0.8, 1.0, 1.0],
border_color: [0.0, 0.0, 0.2, 1.0],
board_edge_color: [0.0, 0.0, 0.2, 1.0],
section_edge_color: [0.0, 0.0, 0.2, 1.0],
cell_edge_color: [0.0, 0.0, 0.2, 1.0],
board_edge_radius: 3.0,
section_edge_radius: 2.0,
cell_edge_radius: 1.0,
selected_cell_background_color: [0.9, 0.9, 1.0, 1.0],
text_color: [0.0, 0.0, 0.1, 1.0],
loaded_cell_background_color: [1.0, 1.0, 1.0, 1.0],
invalid_cell_background_color: [1.0, 0.0, 0.0, 1.0],
invalid_selected_cell_background_color: [1.0, 0.0, 0.5, 1.0],
completed_background_color: [0.0, 1.0, 0.0, 1.0],
}
}
}
pub struct GameboardView {
pub settings: GameboardViewSettings,
}
impl GameboardView {
pub fn new(settings: GameboardViewSettings) -> GameboardView {
GameboardView { settings: settings }
}
pub fn draw<G: Graphics, C>(
&self,
controller: &GameboardController,
glyphs: &mut C,
c: &Context,
g: &mut G,
) where
C: CharacterCache<Texture = G::Texture>,
{
use graphics::{Image, Line, Rectangle, Transformed};
let ref settings = self.settings;
let board_rect = [
settings.position[0],
settings.position[1],
settings.size,
settings.size,
];
if controller.gameboard.completed {
Rectangle::new(settings.completed_background_color).draw(
board_rect,
&c.draw_state,
c.transform,
g,
);
} else {
Rectangle::new(settings.background_color).draw(
board_rect,
&c.draw_state,
c.transform,
g,
);
for i in 0..9 {
for j in 0..9 {
if controller.gameboard.cells[i][j].loaded {
color_cell(
settings,
[j, i],
settings.loaded_cell_background_color,
c,
g,
);
} else if controller.gameboard.cells[i][j].invalid {
color_cell(
settings,
[j, i],
settings.invalid_cell_background_color,
c,
g,
);
}
}
}
if let Some(ind) = controller.selected_cell {
let cell = controller.gameboard.cells[ind[1]][ind[0]];
let color = if !cell.loaded {
if !cell.invalid {
settings.selected_cell_background_color
} else {
settings.invalid_selected_cell_background_color
}
} else {
settings.loaded_cell_background_color
};
color_cell(settings, ind, color, c, g);
}
}
let text_image = Image::new_color(settings.text_color);
let cell_size = settings.size / 9.0;
for j in 0..9 {
for i in 0..9 {
if let Some(ch) = controller.gameboard.char([i, j]) {
let pos = [
settings.position[0] + i as f64 * cell_size + 15.0,
settings.position[1] + j as f64 * cell_size + 34.0,
];
if let Ok(character) = glyphs.character(34, ch) {
let ch_x = pos[0] + character.left();
let ch_y = pos[1] - character.top();
let text_image = text_image.src_rect([
character.atlas_offset[0],
character.atlas_offset[1],
character.atlas_size[0],
character.atlas_size[1],
]);
text_image.draw(
character.texture,
&c.draw_state,
c.transform.trans(ch_x, ch_y),
g,
);
}
}
}
}
let cell_edge = Line::new(settings.cell_edge_color, settings.cell_edge_radius);
let section_edge = Line::new(settings.section_edge_color, settings.section_edge_radius);
for i in 0..9 {
let x = settings.position[0] + i as f64 / 9.0 * settings.size;
let y = settings.position[1] + i as f64 / 9.0 * settings.size;
let x2 = settings.position[0] + settings.size;
let y2 = settings.position[1] + settings.size;
let vline = [x, settings.position[1], x, y2];
let hline = [settings.position[0], y, x2, y];
if (i % 3) == 0 {
section_edge.draw(vline, &c.draw_state, c.transform, g);
section_edge.draw(hline, &c.draw_state, c.transform, g);
} else {
cell_edge.draw(vline, &c.draw_state, c.transform, g);
cell_edge.draw(hline, &c.draw_state, c.transform, g);
}
}
Rectangle::new_border(settings.board_edge_color, settings.board_edge_radius).draw(
board_rect,
&c.draw_state,
c.transform,
g,
);
}
}
fn color_cell<G: Graphics>(
settings: &GameboardViewSettings,
ind: [usize; 2],
color: [f32; 4],
c: &Context,
g: &mut G,
) {
use graphics::Rectangle;
let cell_size = settings.size / 9.0;
let pos = [ind[0] as f64 * cell_size, ind[1] as f64 * cell_size];
let cell_rect = [
settings.position[0] + pos[0],
settings.position[1] + pos[1],
cell_size,
cell_size,
];
Rectangle::new(color).draw(cell_rect, &c.draw_state, c.transform, g);
}

View File

@@ -0,0 +1,57 @@
//////#![deny(missing_docs)]
//! An Sudoko please.
extern crate glutin_window;
use glutin_window::GlutinWindow;
use opengl_graphics::{Filter, GlGraphics, GlyphCache, OpenGL, TextureSettings};
use piston::event_loop::{EventSettings, Events};
use piston::{EventLoop, RenderEvent, WindowSettings};
pub use crate::gameboard::Gameboard;
pub use crate::gameboard_controller::GameboardController;
pub use crate::gameboard_view::{GameboardView, GameboardViewSettings};
mod gameboard;
mod gameboard_controller;
mod gameboard_view;
fn main() {
let opengl = OpenGL::V3_2;
let settings = WindowSettings::new("Sudoku", (640, 480))
.exit_on_esc(true)
.graphics_api(opengl)
.vsync(true);
let mut window: GlutinWindow = settings.build().expect("could not create window");
let mut events = Events::new(EventSettings::new().lazy(true));
let mut gl = GlGraphics::new(opengl);
let args: Vec<_> = std::env::args().collect();
let infile = args.get(1).expect("usage: sudoku <sdm-file>");
let gameboard = Gameboard::load_sdm(infile);
let mut gameboard_controller = GameboardController::new(gameboard);
let gameboard_view_settings = GameboardViewSettings::new();
let gameboard_view = GameboardView::new(gameboard_view_settings);
let texture_settings = TextureSettings::new().filter(Filter::Nearest);
let ref mut glyphs = GlyphCache::new("assets/FiraSans-Regular.ttf", (), texture_settings)
.expect("Could not load font");
while let Some(e) = events.next(&mut window) {
gameboard_controller.event(
gameboard_view.settings.position,
gameboard_view.settings.size,
&e,
);
if let Some(args) = e.render_args() {
gl.draw(args.viewport(), |c, g| {
use graphics::clear;
clear([1.0; 4], g);
gameboard_view.draw(&gameboard_controller, glyphs, &c, g);
})
}
}
}

View File

@@ -0,0 +1 @@
517962483236847915498351762371695248654218397829734156765129834142583679983476520

View File

@@ -0,0 +1 @@
016400000200009000400000062070230100100000003003087040960000005000800007000006820

85
rustbook/guessing_game/Cargo.lock generated Normal file
View File

@@ -0,0 +1,85 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "guessing_game"
version = "0.1.0"
dependencies = [
"rand",
]
[[package]]
name = "libc"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"

View File

@@ -7,4 +7,4 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.6.0"
rand = "0.8.3"

View File

@@ -5,7 +5,7 @@ use std::io;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
let secret_number = rand::thread_rng().gen_range(1..=100);
loop {
println!("Please input your guess.");

View File

@@ -0,0 +1,27 @@
const SEP: &str = "\n---- bleh ----\n";
fn main() {
println!("Hello, world!");
println!("{}", SEP);
println!("0x{:x}", 0b1111_1010_1111_1010_1111_1010_1111);
println!("0b{:b}", 0xfafafaf);
println!("{}", 0xfafafaf);
println!("{}", 0xfeefee);
println!("0b{:b}", 0xfeefee);
println!("{}", SEP);
let sum = 5 + 10;
let difference = 95.5 - 4.3;
let product = 4 * 30;
let quotient = 56.7 / 32.2;
let remainder = 43 % 5;
println!("sum: {}", sum);
println!("difference: {}", difference);
println!("product: {}", product);
println!("quotient: {}", quotient);
println!("remainder: {}", remainder);
}

BIN
rustbook/hello_world/main Executable file

Binary file not shown.

View File

@@ -1,7 +1,11 @@
/custom_types/*
/hello/*
/primitives/*
/variable_bindings/*
/types/*
!/custom_types/*.rs
!/hello/*.rs
!/primitives/*.rs
!/variable_bindings/*.rs
!/types/*.rs

View File

@@ -0,0 +1,16 @@
static LANGUAGE: &str = "Rust";
const THRESHOLD: i32 = 10;
fn is_big(n: i32) -> bool {
n > THRESHOLD
}
fn main() {
let n = 16;
println!("This is {}", LANGUAGE);
println!("The threshold is {}", THRESHOLD);
println!("{} is {}", n, if is_big(n) { "big" } else { "small" });
// THRESHOLD = 5;
}

View File

@@ -0,0 +1,33 @@
enum WebEvent {
PageLoad,
PageUnload,
KeyPress(char),
Paste(String),
Click { x: i64, y: i64 },
}
fn inspect(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("page loaded"),
WebEvent::PageUnload => println!("page unloaded"),
WebEvent::KeyPress(c) => println!("pressed '{}'.", c),
WebEvent::Paste(s) => println!("pasted \"{}\".", s),
WebEvent::Click { x, y } => {
println!("clicked at x={}, y={}.", x, y);
}
}
}
fn main() {
let pressed = WebEvent::KeyPress('x');
let pasted = WebEvent::Paste("my text".to_owned());
let click = WebEvent::Click { x: 20, y: 80 };
let load = WebEvent::PageLoad;
let unload = WebEvent::PageUnload;
inspect(pressed);
inspect(pasted);
inspect(click);
inspect(load);
inspect(unload);
}

View File

@@ -0,0 +1,21 @@
#![allow(dead_code)]
enum Number {
Zero,
One,
Two,
}
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
}
fn main() {
println!("zero is {}", Number::Zero as i32);
println!("one is {}", Number::One as i32);
println!("roses are #{:06x}", Color::Red as i32);
println!("violets are #{:06x}", Color::Blue as i32);
}

View File

@@ -0,0 +1,45 @@
use crate::List::*;
enum List {
Cons(u32, Box<List>),
Nil,
}
impl List {
fn new() -> List {
Nil
}
fn prepend(self, elem: u32) -> List {
Cons(elem, Box::new(self))
}
fn len(&self) -> u32 {
match *self {
Cons(_, ref tail) => 1 + tail.len(),
Nil => 0,
}
}
fn stringify(&self) -> String {
match *self {
Cons(head, ref tail) => {
format!("{}, {}", head, tail.stringify())
}
Nil => {
format!("Nil")
}
}
}
}
fn main() {
let mut list = List::new();
list = list.prepend(1);
list = list.prepend(2);
list = list.prepend(3);
println!("linked list has length: {}", list.len());
println!("{}", list.stringify());
}

View File

@@ -0,0 +1,29 @@
#![allow(dead_code)]
enum Status {
Rich,
Poor,
}
enum Work {
Civilian,
Soldier,
}
fn main() {
use crate::Status::{Poor, Rich};
use crate::Work::*;
let status = Poor;
let work = Civilian;
match status {
Rich => println!("The rich have lots of money!"),
Poor => println!("The poor have no money..."),
}
match work {
Civilian => println!("Civilians work!"),
Soldier => println!("Soldiers fight!"),
}
}

View File

@@ -0,0 +1,15 @@
type NanoSecond = u64;
type Inch = u64;
#[allow(non_camel_case_types)]
type u64_t = u64;
fn main() {
let nanoseconds: NanoSecond = 5 as u64_t;
let inches: Inch = 2 as u64_t;
println!("{} nanoseconds + {} inches = {} unit?",
nanoseconds,
inches,
nanoseconds + inches);
}

View File

@@ -0,0 +1,52 @@
#![allow(overflowing_literals)]
fn main() {
let decimal = 65.4321_f32;
// let integer: u8 = decimal;
let integer = decimal as u8;
let character = integer as char;
// let character = decimal as char;
println!("Casting: {} -> {} -> {}", decimal, integer, character);
println!("1000 as u16 is: {}", 1000 as u16);
println!("1000 as u8 is: {}", 1000 as u8);
println!(" -1 as u8 is: {}", (-1i8) as u8);
println!("1000 mod 256 is: {}", 1000 % 256);
println!(" 128 as a i16 is: {}", 128 as i16);
println!(" 128 as a i8 is: {}", 128 as i8);
println!("1000 as a u8 is: {}", 1000 as u8);
println!(" 232 as a i8 is: {}", 232 as i8);
println!("300.0 as u8 is {}", 300.0_f32 as u8);
println!("-100.0 as u8 is {}", -100.0_f32 as u8);
println!("nan as u8 is {}", f32::NAN as u8);
unsafe {
println!(
"300.0 as u8 is {} (unchecked)",
300.0_f32.to_int_unchecked::<u8>()
);
println!(
"-100.0 as u8 is {} (unchecked)",
(-100.0_f32).to_int_unchecked::<u8>()
);
println!(
"nan as u8 is {} (unchecked)",
f32::NAN.to_int_unchecked::<u8>()
);
}
}

View File

@@ -0,0 +1,9 @@
fn main() {
let elem = 5u8;
let mut vec = Vec::new();
vec.push(elem);
println!("{:?}", vec);
}

View File

@@ -0,0 +1,14 @@
fn main() {
let x = 1u8;
let y = 2u32;
let z = 3f32;
let i = 1;
let f = 1.0;
println!("size of `x` in bytes: {}", std::mem::size_of_val(&x));
println!("size of `y` in bytes: {}", std::mem::size_of_val(&y));
println!("size of `z` in bytes: {}", std::mem::size_of_val(&z));
println!("size of `i` in bytes: {}", std::mem::size_of_val(&i));
println!("size of `f` in bytes: {}", std::mem::size_of_val(&f));
}

View File

@@ -0,0 +1,19 @@
fn main() {
let a_binding;
{
let x = 2;
a_binding = x * x;
}
println!("a binding: {}", a_binding);
let another_binding;
//println!("another binding: {}", another_binding);
another_binding = 1;
println!("another binding: {}", another_binding);
}

View File

@@ -0,0 +1,11 @@
fn main() {
let mut _mutable_integer = 7i32;
{
let _mutable_integer = _mutable_integer;
// _mutable_integer = 50;
}
_mutable_integer = 3;
}

View File

@@ -0,0 +1,12 @@
fn main() {
let _immutable_binding = 1;
let mut mutable_binding = 1;
println!("Before mutation: {}", mutable_binding);
mutable_binding += 1;
println!("After mutation: {}", mutable_binding);
// _immutable_binding += 1;
}

View File

@@ -0,0 +1,12 @@
fn main() {
let long_lived_binding = 1;
{
let short_lived_binding = 2;
println!("inner short: {}", short_lived_binding);
}
// println!("outer short: {}", short_lived_binding);
println!("outer long: {}", long_lived_binding);
}

View File

@@ -0,0 +1,16 @@
fn main() {
let shadowed_binding = 1;
{
println!("before being shadowed: {}", shadowed_binding);
let shadowed_binding = "abc";
println!("shadowed in inner block: {}", shadowed_binding);
}
println!("outside inner block: {}", shadowed_binding);
let shadowed_binding = 2;
println!("shadowed in outer block: {}", shadowed_binding);
}

View File

@@ -0,0 +1,15 @@
fn main() {
let an_integer = 1u32;
let a_boolean = true;
let unit = ();
let copied_integer = an_integer;
println!("An integer: {:?}", copied_integer);
println!("A boolean: {:?}", a_boolean);
println!("Meet the unit value: {:?}", unit);
let _unused_variable = 3u32;
let noisy_unused_variable = 2u32;
}

View File

@@ -1,54 +0,0 @@
#!/usr/bin/env oh-no
set shell := ["python", "-c"]
set something
alias d := dogs
export HOTDOGPARTY := hats
now_ish := `print("oh gee")` + `print(sum([1, 2, 5]))`
an_string := "sit ready \"for reals\" 'uh huh' {{an_raw_string + '{{what' }}"
an_raw_string := 'sit ready "wow" {{not_gonna}}'
hats := '''
very serious hat's
'''
wats := """
{{an_string}} \"yay\" 'ok'
{{ 'dog' + just_executable()}}
{{justfile()}}
{{justfile_directory()}}
{{arch()}} {{os()}}
"""
serious_business := ```
from __future__ import print_function
import os
import datetime
print(f"home: {os.environ.get("HOME", "?")}")
print(f"now-ish: {datetime.datetime.now()}")
```
dogs: aminal manimal _secret
# show the aminal by kind
aminal kind='dog':
#!/usr/bin/env python
import sys
import os
print('\n'.join(os.environ.keys()), file=sys.stderr)
_secret +WHATEVER='OK':
@print("don't tell anyone {{WHATEVER}}")
manimal:
@print('wow')

View File

@@ -1 +0,0 @@
autocmd BufReadPost justfile,*.justfile setfiletype just

View File

@@ -1,80 +0,0 @@
" Vim syntax file
" Language: Just Command Runner
" Maintainer: Dan Buch <dan@meatballhat.com>
" Latest Revision: 28 May 2021
if exists("b:current_syntax")
finish
endif
let b:shell_syntax = "sh"
if exists("g:just_shell_syntax")
let b:shell_syntax = g:just_shell_syntax
endif
exe "syn include @setshellsyntax syntax/" . b:shell_syntax . ".vim"
syn keyword justKeyword alias export if else set
syn keyword justFunction arch os os_family
syn keyword justFunction env_var env_var_or_default invocation_directory
syn keyword justFunction justfile justfile_directory just_executable
syn keyword justSetting shell export dotenv-load positional-arguments
syn match justOperator "\v:"
syn match justOperator "\v\)"
syn match justOperator "\v\("
syn match justOperator "\v\+"
syn match justOperator "\v\@"
syn match justOperator "\v\="
syn match justOperator "\v:\="
syn match justQuote '\v"'
syn match justQuote "\v'"
syn match justQuote '\v"""'
syn match justQuote "\v'''"
syn match justBacktick "\v\`"
syn match justBacktick "\v\`\`\`"
syn match justCurlyBrace "\v\{\{"
syn match justCurlyBrace "\v\}\}"
syn match justComment "\v#.*$"
syn match justShebang "\v^ *#!.*$"
syn match justPublicName "\v[a-zA-Z][_a-zA-Z0-9-]*[a-zA-Z0-9_]"
syn match justPrivateName "\v_[a-zA-Z0-9][_a-zA-Z0-9-]*[a-zA-Z0-9_]"
syn region justCurlyBraced matchgroup=justCurlyBrace start="\v\{\{" skip="\v\\\{" end="\v\}\}" contains=justKeyword,justFunction,justOperator,justQuote,justString,justRawString
syn region justString matchgroup=justQuote start='\v"' skip='\v\\"' end='\v"' contains=justCurlyBraced
syn region justString matchgroup=justQuote start='\v"""' skip='\v\\"' end='\v"""' contains=justCurlyBraced
syn region justRawString matchgroup=justQuote start="\v'" end="\v'"
syn region justRawString matchgroup=justQuote start="\v'''" end="\v'''"
syn region justSubshell matchgroup=justBacktick start="\v\`" skip="\v\\\`" end="\v\`" contains=@setshellsyntax
syn region justSubshell matchgroup=justBacktick start="\v\`\`\`" skip="\v\\\`" end="\v\`\`\`" contains=@setshellsyntax
syn region justRecipeBody start="\v^ *" end="$" keepend contains=@setshellsyntax
syn region justRecipeNoechoBody start="\v^ *\@" end="$" keepend contains=justOperator,@setshellsyntax
hi def link justPublicName Constant
hi def link justPrivateName Constant
hi def link justKeyword Keyword
hi def link justSetting Keyword
hi def link justOperator Operator
hi def link justComment Comment
hi def link justShebang PreProc
hi def link justFunction Function
hi def link justQuote String
hi def link justString String
hi def link justRawString String
hi def link justCurlyBrace Keyword
hi def link justBacktick Special
let b:current_syntax = "just"
" vim:expandtab:ts=2:sts=2