Inlägg

Inlägg som VirtualIntent har skrivit i forumet
Av VirtualIntent

Dag 20, Python

Okej den här var plågsam. Först när jag visualiserade grafen så kunde jag se hur jag skulle lösa uppgiften.

lines = open('input20.txt', 'rt').read().split('\n') module_kind = {} module_targets = {} for l in lines: a, b = l.split(' -> ') targets = b.split(', ') if a == 'broadcaster': kind, name = 'b', a else: kind, name = a[0], a[1:] module_kind[name] = kind module_targets[name] = targets def get_initial_memory(): memory = {} for name, kind in module_kind.items(): if kind == '%': memory[name] = 0 elif kind == '&': memory[name] = {} for name, targets in module_targets.items(): for target in targets: kind = module_kind.get(target) if kind == '&': memory[target][name] = 0 return memory def process_pulses(pulses, memory): while pulses: sender, level, name = pulses.pop(0) kind = module_kind.get(name) targets = module_targets.get(name) if kind == 'b': for target in targets: pulses.append((name, level, target)) elif kind == '%': if level == 0: level = memory.get(name, 0) ^ 1 memory[name] = level for target in targets: pulses.append((name, level, target)) elif kind == '&': if level == 1 and 'rx' in targets: return True mem = memory.get(name, {}) mem[sender] = level level = 0 if all(x == 1 for x in mem.values()) else 1 for target in targets: pulses.append((name, level, target)) return False prod = 1 for n in module_targets['broadcaster']: memory = get_initial_memory() steps = 0 while True: steps += 1 pulses = [('broadcaster', 0, n)] if process_pulses(pulses, memory): prod *= steps break print(prod)

Dold text
Av VirtualIntent

Dag 19, Python

Det känns som att uppgifterna är ganska ojämna nu mot slutet, ibland känns dom svåra och ibland känns det som att det inte går att göra fel. Idag var det senare fallet.

lines = open('input19.txt', 'rt').read().split('\n') def parse_rules_parts(lines): LETTER_TO_INDEX = {'x': 0, 'm': 1, 'a': 2, 's': 3} rules = {} parts = [] for line in lines: if line == '': pass elif line[0] != '{': pos = line.find('{') name = line[:pos] xs = line[pos+1:-1].split(',') rule = [] for x in xs: pos = x.find(':') if pos != -1: clause = (LETTER_TO_INDEX[x[0]], x[1], int(x[2:pos]), x[pos+1:]) else: clause = (0, '', 0, x) rule.append(clause) rules[name] = rule else: xs = line[1:-1].split(',') xs = tuple(int(x.split('=')[1]) for x in xs) parts.append(xs) return rules, parts def evaluate(rule, limits, queues_to_evaluate, accepted): for clause in rule: index, comparison, value, target = clause limit_min, limit_max = limits[index] if comparison == '<': match_min, match_max = limit_min, value-1 keep_min, keep_max = value, limit_max elif comparison == '>': match_min, match_max = value+1, limit_max keep_min, keep_max = limit_min, value else: match_min, match_max = limit_min, limit_max keep_min, keep_max = 1, 0 if match_min <= match_max: match_limits = tuple(((match_min, match_max) if i == index else p for i, p in enumerate(limits))) if target == 'A': accepted.append(match_limits) elif target != 'R': queues_to_evaluate.append((target, match_limits)) if keep_min <= keep_max: limits = tuple(((keep_min, keep_max) if i == index else p for i, p in enumerate(limits))) else: break rules, _ = parse_rules_parts(lines) queues_to_evaluate = [('in', ((1, 4000), (1, 4000), (1, 4000), (1, 4000)))] accepted = [] while queues_to_evaluate: queue_name, limits = queues_to_evaluate.pop() rule = rules[queue_name] evaluate(rule, limits, queues_to_evaluate, accepted) res = 0 for limits in accepted: elements = 1 for limit_min, limit_max in limits: elements *= limit_max - limit_min + 1 res += elements print(res)

Dold text
Av VirtualIntent

Dag 18, Python

lines = open('input18.txt', 'rt').read().split('\n') def get_instructions_part1(lines): directions = {'R': 0, 'D': 1, 'L': 2, 'U': 3} instructions = [] for l in lines: dir, length, _ = l.split() dir = directions[dir] length = int(length) instructions.append((dir, length)) return instructions def get_instructions_part2(lines): instructions = [] for l in lines: _, _, instr = l.split() length = int(instr[2:-2], 16) dir = int(instr[-2]) instructions.append((dir, length)) return instructions def generate_vectors(instructions): offsets = [(1, 0), (0, 1), (-1, 0), (0, -1)] vectors = [] x, y = 0, 0 prev_dir_outline = (instructions[-1][0] + 3) & 3 for dir, length in instructions: dir_outline = (dir + 3) & 3 dx1, dy1 = offsets[prev_dir_outline] dx2, dy2 = offsets[dir_outline] outline_x = x + (dx1 + dx2) * 0.5 outline_y = y + (dy1 + dy2) * 0.5 vectors.append((outline_x, outline_y)) dx, dy = offsets[dir] x += dx * length y += dy * length prev_dir_outline = dir_outline return vectors def inside_triangle(v0, v1, v2, v): tr = [v0, v1, v2] for i in range(3): vo = tr[i] vn = tr[(i + 1) % 3] e = (vn[0] - vo[0], vn[1] - vo[1]) w = (v[0] - vo[0], v[1] - vo[1]) cross = e[0] * w[1] - e[1] * w[0] if cross < 0: return False return True def correctly_winded_triangle(v0, v1, v2): e1 = (v1[0] - v0[0], v1[1] - v0[1]) e2 = (v2[0] - v1[0], v2[1] - v1[1]) cross = e1[0] * e2[1] - e1[1] * e2[0] return cross >= 0 def triangulize(vectors): triangles = [] while len(vectors) > 3: n = len(vectors) for i in range(n): vm1 = vectors[(i - 1) % n] v0 = vectors[i] v1 = vectors[(i + 1) % n] if not correctly_winded_triangle(vm1, v0, v1): continue is_ear = True for j in range(n - 3): v = vectors[(i + 2 + j) % n] if inside_triangle(vm1, v0, v1, v): is_ear = False break if is_ear: triangles.append((vm1, v0, v1)) del vectors[i] break triangles.append(tuple(vectors)) return triangles def calculate_total_area(triangles): total_area = 0 for v0, v1, v2 in triangles: x0, y0 = v0 x1, y1 = v1 x2, y2 = v2 area = abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) / 2 total_area += area return total_area instructions = get_instructions_part2(lines) vectors = generate_vectors(instructions) triangles = triangulize(vectors) total_area = calculate_total_area(triangles) print(total_area)

Dold text
Av VirtualIntent

Dag 17 i Python

Dagens övning var inte busenkel. Ljusningen var att del två gick snabbt när väl del ett fungerade.

Min lösning är Dijkstra på grafen där varje nod är (position, historia), där historian är den senaste riktningen samt hur många steg som tagits i den riktningen för att komma till positionen.

lines = open('input17.txt', 'rt').read().split('\n') H = len(lines) W = len(lines[0]) RIGHT = 0 DOWN = 1 LEFT = 2 UP = 3 x_offs = [1, 0, -1, 0] y_offs = [0, 1, 0, -1] start = (0, 0, RIGHT, 0) import heapq dist_heap = [(0, start)] dist_dict = {start: 0} found = {} part_no = 2 def allowed_dir(dir, dir_count, next_dir): if part_no == 1: if next_dir == dir: if dir_count == 3: return False elif next_dir == ((dir + 2) & 3): return False return True else: if next_dir == dir: if dir_count == 10: return False elif next_dir == ((dir + 2) & 3): return False elif dir_count < 4: return False return True while dist_heap: d, state = heapq.heappop(dist_heap) del dist_dict[state] found[state] = d y, x, dir, dir_count = state if y == H-1 and x == W-1: if part_no == 1 or dir_count >= 4: print(d) break for next_dir in range(4): next_y = y + y_offs[next_dir] next_x = x + x_offs[next_dir] if next_y < 0 or next_y >= H or next_x < 0 or next_x >= W: continue if not allowed_dir(dir, dir_count, next_dir): continue next_dir_count = 1 + (dir_count if next_dir == dir else 0) next_state = (next_y, next_x, next_dir, next_dir_count) if next_state in found: continue cost = int(lines[next_y][next_x]) next_d = d + cost prev_d = dist_dict.get(next_state) add_state = prev_d is None or next_d < prev_d if prev_d is not None and add_state: dist_heap.remove((prev_d, next_state)) heapq.heapify(dist_heap) if add_state: heapq.heappush(dist_heap, (next_d, next_state)) dist_dict[next_state] = next_d

Dold text
Av VirtualIntent

Dag 16 i Python

lines = open('input16.txt', 'rt').read().split('\n') H = len(lines) W = len(lines[0]) L2R = 1 T2B = 2 R2L = 4 B2T = 8 TURN_SLASH = {L2R: B2T, T2B: R2L, R2L: T2B, B2T: L2R} TURN_BACKSLASH = {L2R: T2B, T2B: L2R, R2L: B2T, B2T: R2L} def follow_beam(y, x, dir): while True: if y < 0 or y >= H or x < 0 or x >= W: return if energized[y][x] & dir: return energized[y][x] |= dir c = lines[y][x] if c == '/': dir = TURN_SLASH[dir] elif c == '\\': dir = TURN_BACKSLASH[dir] elif c == '|' and dir in (L2R, R2L): stack.append((y-1, x, B2T)) dir = T2B elif c == '-' and dir in (T2B, B2T): stack.append((y, x-1, R2L)) dir = L2R if dir == L2R: x += 1 elif dir == T2B: y += 1 elif dir == R2L: x -= 1 elif dir == B2T: y -= 1 energized = [[0] * W for _ in range(H)] stack = [] max_tiles_energized = 0 for start_dir in [L2R, T2B, R2L, B2T]: n = H if start_dir in (L2R, R2L) else W for i in range(n): energized = [[0] * W for _ in range(H)] if start_dir == L2R: stack = [(i, 0, start_dir)] elif start_dir == T2B: stack = [(0, i, start_dir)] elif start_dir == R2L: stack = [(i, W-1, start_dir)] elif start_dir == B2T: stack = [(H-1, i, start_dir)] while stack: y, x, dir = stack.pop(0) follow_beam(y, x, dir) tiles_energized = sum(1 if x else 0 for row in energized for x in row) if max_tiles_energized < tiles_energized: max_tiles_energized = tiles_energized print(max_tiles_energized)

Dold text
Av VirtualIntent

Dag 15 i Python

Efter allt prat om hashmaps i uppgiftens beskrivning så var jag lite överraskad över att det fungerar bra att använda bara en array för att hålla linserna i varje box.

commands = open('input15.txt', 'rt').read().split(',') def hash_algo(s): v = 0 for c in s: v = ((v + ord(c)) * 17) & 255 return v boxes = [[] for _ in range(256)] for command in commands: pos = command.find('=') if pos != -1: label, power = command[:pos], int(command[pos+1:]) box = boxes[hash_algo(label)] in_box = False for i, (lab, _) in enumerate(box): if lab == label: box[i] = (label, power) in_box = True break if not in_box: box.append((label, power)) else: label = command[:-1] box = boxes[hash_algo(label)] for i, (lab, _) in enumerate(box): if lab == label: del box[i] break res = 0 for i, box in enumerate(boxes): for j, (_, power) in enumerate(box): res += (i+1) * (j+1) * power print(res)

Dold text
Av VirtualIntent

Dag 14 i Python

lines = open('input14.txt', 'rt').read().split('\n') pattern0 = tuple(tuple(l) for l in lines) H = len(pattern0) W = len(pattern0[0]) def tilt_north(pattern): mutable_pattern = [list(l) for l in pattern] for y in range(1, H): for x in range(W): if mutable_pattern[y][x] == 'O': new_y = y for y2 in range(y-1, -1, -1): if mutable_pattern[y2][x] == '.': new_y = y2 else: break if new_y != y: mutable_pattern[y][x] = '.' mutable_pattern[new_y][x] = 'O' return tuple(tuple(l) for l in mutable_pattern) def rotate_90(pattern): return tuple(tuple(pattern[H - 1 - x][y] for x in range(W)) for y in range(H)) period = 0 offset = 0 patterns = {} pattern = pattern0 N = 1000000000 for spins in range(1, N): for _ in range(4): pattern = tilt_north(pattern) pattern = rotate_90(pattern) last_occurrence = patterns.get(pattern) if last_occurrence is not None: period = spins - last_occurrence offset = spins break patterns[pattern] = spins patterns = ((i, t) for t, i in patterns.items()) patterns = [t for _, t in sorted(patterns)] patterns = patterns[-period:] def calculate_load(pattern): return sum(sum(c == 'O' for c in row) * (H - y) for y, row in enumerate(pattern)) pattern_index = (N - offset) % period pattern = patterns[pattern_index] print(calculate_load(pattern))

Dold text
Av VirtualIntent

Dag 12 i Python

lines = open('input12.txt', 'rt').read().split('\n') combinations_cache = {} def combinations_cache_lookup(pos, group_index, group_len): v = combinations_cache.get((pos, group_index, group_len)) if v is None: v = combinations(pos, group_index, group_len) combinations_cache[(pos, group_index, group_len)] = v return v def combinations(pos, group_index, group_len): if pos == len(row): if group_len == 0: return 1 if group_index == len(groups) else 0 else: return 1 if group_index == len(groups) - 1 and groups[group_index] == group_len else 0 valid = 0 if row[pos] == '.' or row[pos] == '?': if group_len == 0: valid += combinations_cache_lookup(pos+1, group_index, 0) elif groups[group_index] == group_len: valid += combinations_cache_lookup(pos+1, group_index+1, 0) if row[pos] == '#' or row[pos] == '?': if group_index < len(groups) and group_len < groups[group_index]: valid += combinations_cache_lookup(pos+1, group_index, group_len+1) return valid res = 0 for l in lines: row, groups = l.split() groups = [int(x) for x in groups.split(',')] row = '?'.join([row] * 5) groups = groups * 5 combinations_cache.clear() valid = combinations(0, 0, 0) res += valid print(res)

Dold text
Av VirtualIntent

Jag och en kompis har gjort en expansion till Amiga 500 som vi kallar för A314. Expansionen gör att en Raspberry Pi agerar som en koprocessor till Amigan, och kan användas till diverse olika saker. Mer beskrivning och all information för att bygga ett eget kort finns här: https://github.com/niklasekstrom/a314.

https://i.imgur.com/eT0zBH5.jpg

Av VirtualIntent

Jag och en kompis har gjort ett expansionskort till Amiga 500 som har en Raspberry Pi på kortet. Kortet kallas A314 och är helt open source och finns beskrivet här: https://github.com/niklasekstrom/a314. Det gör att Amigan kan accessa filer på raspens sd-kort och köra kommandon på raspen ifrån Amigans kommandorad.

https://raw.githubusercontent.com/niklasekstrom/a314/master/Docu...

Av VirtualIntent
Skrivet av EpicJoey:

Det är en bra dator men jag har en MacBook Pro också

Men den MacBook Pro hade du säkert innan du köpte Dell XPS också, det lär ha varit någonting som fick dig att ändra dig?

Kan du säga nått om ungefär vid vilken prisnivå du skulle kunna släppa datorn? Hur mycket gav du för den hos Elgiganten?

Av VirtualIntent

Jag blir nyfiken, vad är det som gjorde att du ändrade dig och inte vill ha datorn längre? Dell XPS ska väl vara en fin laptop, så vitt jag har förstått.

Skickades från m.sweclockers.com

Av VirtualIntent

Jag gjorde en sån lösning i Python, på följande sätt: jag sparade en faktura-template i LibreOffices ODT-format. Det formatet är i själva verket en zip-fil och i den så finns en fil contents.xml. Jag skrev en funktion i Python som skapade en egen contents.xml med information från databasen. Sedan gjorde jag en till funktion som skapade en zip-fil med innehållet i ODT-templaten fast med min contents.xml. Sedan lätt jag Python köra (med subprocess.exec) LibreOffice med argumenten "--headless --convert-to pdf" och sen sökvägen till den temporära filen där jag sparade min genererade ODT-fil. På så sätt kunde jag generera fina fakturor med ganska lite jobb.

Av VirtualIntent

I Android M (Marshmallow, 6.0) som kommer ut snart så kommer systemet för rättigheter att göras om. Istället för att en användare godkänner ett gäng rättigheter när appen installeras så kommer Android att fråga användaren första gången som appen vill använda en funktion som kräver en rättighet. Om användaren inte godkänner det så måste appen hantera detta och fortsätta utan att använda funktionen.

Här beskrivs detta, https://developer.android.com/preview/features/runtime-permis..., och här är en video där en Android-utvecklare beskriver det, https://www.youtube.com/watch?v=f17qe9vZ8RM.

Av VirtualIntent
Skrivet av Sir. Haxalot:

Alla tunga jävla java applikationer som har interna dependencies som gör att de inte kan skala ut så det enda alternativet är att köpa fetare servrar.

Kan du ge ett exempel på en sån applikation? Kan den applikationen dra nytta av att ha tillgång till fler kärnor?

Av VirtualIntent
Skrivet av Ernesto:

Någonting som hade varit helt magnifikt hade ju varit om man hade en form av lastbalanserare som löste det automatiskt - Man skickar en hel hög med jobb till balanseraren, som portionerar det till X trådar/processorer/kärnor och den hanterar också svaret och kön. - Då skulle man inte längre ha svårt att skriva program som utnyttjar parallella trådar, utan det skulle skötas automatiskt - Alla program på jorden skulle bli otroligt mycket snabbare!

Ja det låter ju lysande! Om du hade en sån lastbalanserare, vilket typ av program skulle du vilja snabba upp då först och främst?

Skrivet av VexedRelic:

Annars vad gäller tråden så tror jag i vissa fall att det kan bli problem med CPU kopplat i ett nätverk för du kommer ha en latens på millisekunder där instruktioner som utförs av en cpu kan beräknas ned till nano sekunder. Så du kommer troligtvis få en interrupt delay för nätverks lagret inte är lika snabbt.

Precis, så när man skriver programmet så behöver man dela upp programmet i delar som kan köra så mycket fristående (utan att kommunicera/synkronisera) som möjligt. Men så gör man idag också även när man skriver program med många trådar som kör på en (icke-distribuerad) processor med flera kärnor.

Skrivet av VexedRelic:

Fast det beror helt på vad det är för ide du vill skapa eller utföra.

Exakt.

Skrivet av FlashTec:

Vore nog bättre att utnyttja tekniken för att räkna ut något viktigt typ hur man får religion och politik att fungera tillsammans eller hur man får längre räckvidd på elbilar utan att köra med skarvsladd

Det låter som att vi skulle behöva programmera en stark AI som kan lösa alla problem åt oss?

Av VirtualIntent
Skrivet av Erik_T:

Nej, det svåra är att göra program som faktiskt kan dra nytta av mer än ett fåtal trådar.

Vissa problem, som brukar kallas "embarrasingly parallell", är enkla att sprida ut på godtyckligt antal processorer och få en prestandavinst som är näst intill linjär med antalet processorer. Raytracing är ett klassiskt exempel på ett sådant problem.

Den stora merparten av problem/program är däremot svåra att få att utnyttja en massa distribuerade resurser på ett effektivt sätt - och i de flesta fall finns det ingen som vet ens teoretiskt hur man kan göra det.

Jag håller med om ditt resonemang. Men anta att det finns ett antal problem som ligger någonstans mellan "pinsamt parallella" och "inte alls parallella".

Skrivet av Erik_T:

Om man nu rent hypotetiskt antar att det var lätt att parellellisera program, vilka program skulle man vilja göra det med? Svaret är i princip detsamma som det på frågan "Om du kunde få en CPU som var tio gånger snabbare än den du har, vilka program skulle du vilja ha den till?", nämligen: ALLA program som har behov av mer CPU-kraft - vilket är merparten av dem.

Skrivet av lorgix:

Jag kanske missförstår frågan, men jag skulle nog köra typ allt på det viset om det var enkelt.

Frågan är otydligt formulerad, ursäkta för detta.

Men är det verkligen alla program som behöver mera datorresurser? När jag har funderat så kommer jag på ganska många program som inte skulle ha så stor nytta av fler kärnor, så som mejlprogrammet eller nått enkelt spel som sudoku. Det finns en hel del program inom "Big Data-området" som kan använda många kärnor, men denna typ av tillämpning känns lite oinspirerande tycker jag. Jag tänker mig att det borde finnas lite roligare program som man kan köra på sin fritid som faktiskt skulle ha nytta av fler CPU-kärnor än vad som sitter i en enda dator idag.

Jag tänker på när Amigan kom så var den klart kraftfullare än de andra datorerna som fanns, och då utvecklades det program som inte hade gått att göra tidigare. Det fanns en demo-scen där man försökte utnyttja hårdvarans kapacitet maximalt. Jag funderar på vilka program skulle kunna utvecklas om man har en (distribuerad) dator med väldigt många kärnor. Frågan är som sagt väldigt otydlig, så peka gärna ut på vilka sätt jag tänker "fel"!

Av VirtualIntent

Tack för era svar!

Skrivet av Fluf:

Nackdelen att köra saker som MMO AI och liknande är latancy och att alla individer är beroende av varandra på deras reaktioner och positioner så blir enormt mycket overhead och mycket latancy mellan. Optimalt för distribuerad beräkning är när du kan ge delar av uppgifter till olika enheter och sedan samla in och ge nya batchar.

Så min fråga (som jag inser inte var så tydligt ställd) är alltså inte vad som är optimalt för distribuerade beräkningar, utan att ifall det var lika enkelt att skriva ett distribuerat program som ett lokalt program, vad skulle du i så fall vilja utveckla för program som använder många processorkärnor (och andra resurser som minne och disk). Underförstått så antar jag att det finns program som du/ni skulle vilja utveckla men att det inte är aktuellt idag eftersom det är svårt/krångligt att skriva distribuerade program.

Ett spel med kraftfull AI är ett sånt exempel tänker jag, men å andra sidan så finns det väl många andra anledningar utöver att det skulle köra distribuerat som gör att det är svårt att utveckla. Men det kanske finns andra typer av program som inte är speciellt svåra att skriva för att köra lokalt, men där problemet snarare ligger i att köra det distribuerat.

Av VirtualIntent
Skrivet av iXam:

Vad jag skulle göra om det vare lika lätt att programmera ett lokalt system som en distribuerat vore nog en databas utan de problem som finns i dagsläget för att hålla ACID (https://en.wikipedia.org/wiki/ACID) samt att hålla det snabbt.

Men antag att det redan finns en sådan databas då, vad skulle du utveckla för program som använder sig av databasen?

Av VirtualIntent

Förslag på program som kör på tusentals CPU-kärnor?

Om det var lika enkelt att skriva ett program som kör i ett distribuerat system som att skriva ett program som kör lokalt, vad skulle ni hitta på för program då?

Med ett distribuerat system så tänker jag på en (stor) samling datorer som var och en har CPU (flera kärnor), RAM och disk, och som är anslutna med ett nätverk, och ett program som kör på det distribuerade systemet kan använda dessa resurser som att det vore en enda stor dator.

Ett förslag är ett massivt multispelar-spel som har många AI-spelare och som använder tusentals CPU-kärnor för att köra AI och för att simulera fysiken i spelet.

Ett exempel på ett program som används idag är Googles sökmotor som kör på tusentals datorer.