Jag gav upp och kikade pÄ andra lösningar i trÄden och hittade lösningen @gibbon_ postade. Det var inte helt lÀtt att först vad som hÀnde dÀr men efter en hel del pannveckande insÄg jag att det egentligen var en cirkulÀr lista men att han bara höll reda pÄ next-"pekarna" och struntade i koppnumret för det var alltid samma som indexet i tabellen. Man lÀr sig mycket av att lÀsa andras lösningar och jÀmföra med sin egen lösning. Man lÀr sig Ànnu mer om man har tid att skriva om sin egen lösning och byta till en bÀttre metod som nÄgon annan anvÀnt. Offra inte för mycket tid pÄ mina lösningar i ful-Python och gibbon_s awk, vi har inte haft lÀttlÀsthet högst upp pÄ prioritetslistan
Jag Àr ganska nöjd med de lösningar jag kom upp med, men nÄgot jag kan helt sÀkert sÀga Àr att de absolut hade sett vÀldigt annorlunda ut om jag gjort dem i nÄgot annat sprÄk. Det hÀr knepet du nÀmner t.ex. hade jag aldrig kommit pÄ om jag inte varit sÄ begrÀnsad. Jag visste att jag behövde en lÀnkad lista för prestandans skull, och hur gör man dÄ nÀr allt man har Àr en hashmap liksom?
..passar vÀl pÄ att posta nÄgra att de dagar jag inte delade tidigare
NÄgot jag fann intressant hÀr var att jag kunde serialisera data jag annars hade bevarat i strukturer, och bara skickade runt den serialiserade strÀngen istÀllet för strukturerna, som awk inte har stöd för.
<in awk -f d20.awk
d20.awk
BEGIN { for (x = 0; x <= 1; x++) { for (r = 0; r <= 3; r++) { configurations[++c] = x"|"r } } }
/Tile/ { split($2, v, ":"); t = v[1] }
length($0) > 0 && $0 !~ /Tile/ { dim = length($0) - 2; tiles[t] = tiles[t] == "" ? $0 : tiles[t]"|"$0 }
END {
for (t in tiles) { not_fitted[t] }
while (length(not_fitted)) { for (t in not_fitted) { if (try_fit(t)) { delete not_fitted[t] } } }
for (f in fitted) {
split(fitted[f], fc, "|")
split(fc[1], p, ",")
c_max_x = c_max_x > p[1] ? c_max_x : p[1]; c_min_x = c_min_x < p[1] ? c_min_x : p[1]
c_max_y = c_max_y > p[2] ? c_max_y : p[2]; c_min_y = c_min_y < p[2] ? c_min_y : p[2]
}
p1res = 1
for (f in fitted) {
split(fitted[f], fc, "|")
split(fc[1], p, ",")
if (p[1] == c_max_x && p[2] == c_max_y) { p1res *= f }
if (p[1] == c_max_x && p[2] == c_min_y) { p1res *= f }
if (p[1] == c_min_x && p[2] == c_max_y) { p1res *= f }
if (p[1] == c_min_x && p[2] == c_min_y) { p1res *= f }
}
print p1res
for (f in fitted) {
split(fitted[f], fc, "|")
split(fc[1], p, ",")
gx = (p[1] - c_min_x) * dim
gy = ((c_max_y - c_min_y) - (p[2] - c_min_y)) * dim
split(transform(f, fc[2]), trows, "|")
for (r = 2; r < length(trows); r++) {
split(trows[r], tcols, "")
for (c = 2; c < length(tcols); c++) {
grid[(gx + c - 2)" "(gy + r - 2)] = tcols[c]
}
}
}
image = ""
for (y = 0; y < (c_max_y - c_min_y + 1) * dim; y++) {
row = ""
for (x = 0; x < (c_max_x - c_min_x + 1) * dim; x++) {
row = row""grid[x" "y]
}
image = image == "" ? row : image"|"row
}
tiles[0] = image
monster[0] = " # "
monster[1] = "# ## ## ###"
monster[2] = " # # # # # # "
for (y = 0; y < length(monster); y++) {
split(monster[y], mrow, "")
for (x = 0; x < length(mrow); x++) {
if (mrow[x + 1] == "#") {
mon[x" "y]
cmon++
}
}
}
for (c in configurations) {
delete grid
split(transform(0, c), rows, "|")
dimy = length(rows)
for (y = 0; y < length(rows); y++) {
split(rows[y + 1], cols, "")
dimx = length(cols)
for (x = 0; x < length(cols); x++) {
if (cols[x + 1] == "#") { grid[x" "y] }
}
}
found = 0
for (y = 0; y <= dimy - length(monster); y++) {
for (x = 0; x <= dimx - length(monster[0]); x++) {
gottem = 1
for (m in mon) { split(m, p); gottem = gottem && x + p[1]" "y + p[2] in grid }
if (gottem) { found++ }
}
}
if (found != 0) { break }
}
print length(grid) - (found * cmon)
}
function try_fit(t) {
if (length(fitted) == 0) {
fitted[t] = "0,0|1"
return 1
}
delete try_pos
delete elim_pos
for (f in fitted) {
split(fitted[f], fc, "|")
split(fc[1], p, ",")
try_pos[p[1] + 1","p[2]]
try_pos[p[1] - 1","p[2]]
try_pos[p[1]","p[2] + 1]
try_pos[p[1]","p[2] - 1]
elim_pos[fc[1]]
}
for (e in elim_pos) { delete try_pos[e] }
for (pos in try_pos) {
for (cc in configurations) {
if (test_fitting(transform(t, cc), pos)) {
fitted[t] = pos"|"cc
return 1
}
}
}
return 0
}
function test_fitting(tile, pos) {
split(tile, trows, "|")
split(pos, p, ",")
fits = 1
for (f in fitted) {
split(fitted[f], fc, "|")
dir = in_range(pos, fc[1])
if (dir >= 0) { split(transform(f, fc[2]), frows, "|") }
if (dir == 0) { fits = frows[10] == trows[1] }
if (dir == 1) { fits = get_col(1, trows) == get_col(10, frows) }
if (dir == 2) { fits = frows[1] == trows[10] }
if (dir == 3) { fits = get_col(10, trows) == get_col(1, frows) }
if (!fits) { break }
}
return fits
}
function get_col(n, rows) {
col = ""
for (r = 1; r <= length(rows); r++) { col = col""substr(rows[r], n, 1) }
return col
}
function in_range(posa, posb) {
split(posa, pa, ",")
split(posb, pb, ",")
if (pa[1] == pb[1] && pa[2] == (pb[2] - 1)) { return 0 }
if (pa[1] == (pb[1] - 1) && pa[2] == pb[2]) { return 3 }
if (pa[1] == pb[1] && pa[2] == (pb[2] + 1)) { return 2 }
if (pa[1] == (pb[1] + 1) && pa[2] == pb[2]) { return 1 }
return -1
}
function transform(t, c) {
split(configurations[c], cs, "|")
tile = cs[1] ? flip(tiles[t]) : tiles[t]
for (n = 0; n < cs[2]; n++) { tile = rotate(tile) }
return tile
}
function flip(tile) {
split(tile, rows, "|")
new_tile = ""
for (r = 1; r <= length(rows); r++) {
split(rows[r], cols, "")
new_row = ""
for (c = 1; c <= length(cols); c++) { new_row = cols[c]""new_row }
new_tile = new_tile == "" ? new_row : new_tile"|"new_row
}
return new_tile
}
function rotate(tile) {
split(tile, rows, "|")
for (r = 1; r <= length(rows); r++) {
split(rows[r], cols, "")
for (c = 1; c <= length(cols); c++) { rgrid[c" "r] = cols[c] }
max_x = length(cols)
}
max_y = length(rows)
new_tile = ""
for (cy = 1; cy <= max_y; cy++) {
new_row = ""
for (cx = 1; cx <= max_x; cx++) { new_row = new_row""rgrid[cy" "(max_y - cx + 1)] }
new_tile = new_tile == "" ? new_row : new_tile"|"new_row
}
return new_tile
}
<in sed 's/(contains/\|/;s/)//;s/,//g' | awk -f d21.awk
d21.awk
{
split($0, prod, "|")
split(prod[1], ingredients)
split(prod[2], allergens)
for (i in ingredients) { ingredient_count[ingredients[i]]++ }
for (a in allergens) {
sus[allergens[a]] = allergens[a] in sus ? intersection(sus[allergens[a]], prod[1]) : prod[1]
}
}
END {
do {
elim = ""
for (i in sus) {
split(sus[i], xs)
if (length(xs) == 1) {
def[i] = sus[i]
delete sus[i]
elim = elim" "def[i]
}
}
for (i in sus) {
sus[i] = difference(sus[i], elim)
}
} while (length(sus))
for (i in def) {
baddies[def[i]]
allergens_s = allergens_s" "i
}
for (i in ingredient_count) { p1res += i in baddies ? 0 : ingredient_count[i] }
"echo "allergens_s" | tr ' ' '\n' | sort | tr '\n' ' '" | getline sorted_allergens_s
split(sorted_allergens_s, sorted_allergens)
for (i = 1; i <= length(sorted_allergens); i++) {
p2res = p2res == "" ? def[sorted_allergens[i]] : p2res","def[sorted_allergens[i]]
}
print p1res
print p2res
}
function intersection(list_a, list_b) { return set_op(list_a, list_b, "int") }
function difference(list_a, list_b) { return set_op(list_a, list_b, "diff") }
function set_op(list_a, list_b, op) {
split(list_a, as); split(list_b, bs)
delete ibs; for (x in bs) { ibs[bs[x]] }
res = ""
for (x in as) {
test = (op == "diff" && !(as[x] in ibs)) || (op == "int" && (as[x] in ibs));
if (test) { res = res == "" ? as[x] : res" "as[x] }
}
return res
}
Rekursion i awk Àr inte kul, nÀr mer eller mindre allt hamnar i globalt scope.. Skjuter undan lokal data i en liten stash som jag jag kan ÄterstÀlla nÀr jag kommer tillbaka.
<in awk -v p1=1 -f d22.awk
<in awk -f d22.awk
d22.awk
/Player 1/ { reading = 1 }
/Player 2/ { reading = 2 }
/^[0-9]+$/ && reading == 1 { deck1 = append(deck1, $0) }
/^[0-9]+$/ && reading == 2 { deck2 = append(deck2, $0) }
function append(deck, card) { return deck == "" ? card : deck" "card }
END {
winner = play(++tot, deck1, deck2)
split(winner, w, "|")
split(w[2], cards)
for (i = 1; i <= length(cards); i++) { res += cards[i] * (length(cards) - i + 1) }
print res
}
function play(game, deck1, deck2) {
do {
i = match(deck1, " "); c1 = int(i > 0 ? substr(deck1, 1, i - 1) : deck1); deck1 = i > 0 ? substr(deck1, i + 1) : ""
i = match(deck2, " "); c2 = int(i > 0 ? substr(deck2, 1, i - 1) : deck2); deck2 = i > 0 ? substr(deck2, i + 1) : ""
if (p1) { winner = c1 > c2 ? 1 : 2 }
else {
state = game"|"deck1"|"deck2
if (state in memory) { return "1|"deck1 }
memory[state]
split(deck1, cards1); count1 = length(cards1)
split(deck2, cards2); count2 = length(cards2)
if (count1 >= c1 && count2 >= c2) {
stash_p1[game] = c1; stash_p2[game] = c2; stash_deck1[game] = deck1; stash_deck2[game] = deck2
deck1 = ""; for (i = 1; i <= c1; i++) { deck1 = append(deck1, cards1[i]) }
deck2 = ""; for (i = 1; i <= c2; i++) { deck2 = append(deck2, cards2[i]) }
winner = play(++tot, deck1, deck2)
split(winner, w, "|")
winner = w[1]
c1 = stash_p1[game]; c2 = stash_p2[game]; deck1 = stash_deck1[game]; deck2 = stash_deck2[game]
}
else { winner = c1 > c2 ? 1 : 2 }
}
if (winner == 1) {
deck1 = append(deck1, c1)
deck1 = append(deck1, c2)
}
else {
deck2 = append(deck2, c2)
deck2 = append(deck2, c1)
}
} while (deck1 != "" && deck2 != "")
return deck1 == "" ? "2|"deck2 : "1|"deck1
}
"Some poor, phoneless fool is probably sitting next to a waterfall somewhere, totally unaware of how angry and scared he's supposed to be." - Duncan Trussell