Tak było wtedy, ale obecnie wszyscy przeszli na IPv6 . (Dobrze?)
Twoim zadaniem jest napisanie programu, który wypisze wszystkie adresy IPv6 .
Powinieneś napisać pełny program, który nie pobiera danych wejściowych i wypisuje adresy IPv6, po jednym w wierszu i bez innych danych wyjściowych. Twój program musi wydrukować wszystkie 2 128 możliwych adresów, w tym nieprawidłowe. Każdy adres musi zostać wydrukowany dokładnie raz. Możesz wydrukować adresy w dowolnej kolejności.
Każdy adres może być wydrukowany w całości, z 8 grupami 4 cyfr szesnastkowych oddzielonych dwukropkami, np
2001:0db8:85a3:0000:0000:8a2e:0370:7334
Możesz, według własnego uznania, użyć dowolnego ze standardowych skrótów z RFC 5952 :
- Zera wiodące w grupie można pominąć, z tym wyjątkiem, że
0
nie można ich dalej skracać. ::
można użyć maksymalnie raz na adres, aby skrócić sekwencję jednej lub więcej grup zerowych.- Cyfry szesnastkowe mogą używać małych lub wielkich liter.
Jeśli osiągniesz zalecenie dotyczące reprezentacji z RFC 5952 (tylko małe litery, najkrótsza możliwa reprezentacja, z ::
jak najwcześniejszym wykorzystaniem, jeśli istnieje wiele miejsc, w których można jej użyć), otrzymasz bonus -20% .
Ze względu na rozmiar danych wyjściowych, twój program nie powinien zakończyć się, gdy tam siedzimy. W pewnym momencie twój program może zostać przerwany za pomocą środków zewnętrznych ( Ctrl+ C, odłączenie zasilania,…). Twój program musi generować dane wyjściowe w postaci strumienia, aby po „rozsądnym” odczekaniu wygenerował kilka wierszy. Zasadniczo nie jest dozwolone budowanie gigantycznego ciągu w pamięci tylko w celu wydrukowania go na końcu. Każdy program, który zabraknie pamięci na „standardowym” komputerze, zostanie zdyskwalifikowany. (Niemniej jednak, jeśli program pozostawiono na działanie przez wystarczająco długi czas, musi wydrukować wszystkie adresy IPv6, a następnie wyjść).
(Jeśli ten warunek stanowi problem dla interpreterów internetowych, którzy uruchamiają program do zakończenia, a następnie pozwalają zobaczyć wynik, a nie masz hostowanego tłumacza, przetestuj program na mniejszej wersji problemu, a następnie ostrożnie go dostosuj do pełnego 2 128 ).
Twój wynik to długość twojego programu w bajtach, pomnożona przez 0,8, jeśli otrzymasz bonus. To jest golf golfowy, więc wygrywa najniższy wynik.
źródło
Odpowiedzi:
Pyth, 21 bajtów
Używa pętli while ze
J
zmienną iteratora. Inicjuje maksymalne użycie8^chr(' ')
. Blokuje, dodając tę wartość początkową, konwertując na hex, a następnie usuwając pierwszy znak.źródło
Python 3, 65 bajtów · 0,8 = 52,0
źródło
ipaddress
jest tylko python3.Pyth,
272524 bajtówUwaga: kod zawierał wcześniej błąd, który naprawił zapisany 1 bajt
Drukuje adresy jak
Poprzednia (bardziej skomplikowana) wersja wykorzystująca operator pada (również 24 bajty):
Wyjaśnienie
Pyth, 21 bajtów (nieprawidłowy)
Nie można tego uruchomić, ponieważ 1) zużyłoby co najmniej 2 132 bajty (2 52 yobibajtów) pamięci i 2) interpreter go nie lubi (2 128 nie mieści się
ssize_t
, więc nie malist
takiej wielkości) . Wypisuje adresy w kolejności leksykograficznej. Możesz wypróbować algorytm, zmieniając numery na końcu na coś użytecznego.źródło
C (z rozszerzeniami GCC), 76 bajtów * 0,8 = 60,8
Wykorzystuje 128-bitowe rozszerzenie GCC liczb całkowitych, aby po prostu policzyć od
::
doffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
.inet_ntop()
poprawnie formatuje każdy adres, aby można było ubiegać się o premię w wysokości -20%.Wynik
Wykorzystanie
sed
do generowania co milionowej linii do 10 milionów:Uwaga: Używam komputera z małą końcówką x86_64, a adresy sieciowe zwykle są zawsze uporządkowane w sieci (big-endian), więc endianowość jest skutecznie zamieniana za pomocą
inet_ntop()
. To nie ma znaczenia - wszystkie adresy będą nadal (ostatecznie) wyświetlane.źródło
CJam,
3627 bajtów-9 bajtów dzięki @Dennis (zapomniałem, że CJam ma formatowanie ciągów). Drukuje adresy małymi i malejącymi.
Z oczywistych powodów użyj interpretera Java, a nie internetowego. Możesz go jednak zastąpić
G32#
czymś mniejszym do testowania online, np. Oto ostatnie 100 .Wyjaśnienie
źródło
0000:0000:0000:0000:0000:0000:ffff:ffff
. Wygląda na to, że formatowanie łańcucha może działać inaczej w trybie online. Potwierdziłem, że działa dobrze z wersją offline.n
jest taki sam jakoNo
w TIO .Python 2.7, 67 bajtów
Jako efekt uboczny metody zastosowanej do wstawienia dwukropków adresy są drukowane z kolumną znajdującą się najbardziej po prawej stronie, widoczną po lewej stronie:
źródło
[printing] the addresses in any order
. ;)Verilog, 335
Moje pierwsze zgłoszenie Verilog, prawdopodobnie przydałoby się więcej golfa, ale nie mam teraz na to siły.
c
jest zegarem,o
jest wyjściem ASCII. Nie kwalifikuje się do premii za formatowanie ze względu na zerowanie zamiast skrótu.Jest to prosta iteracja, po której następuje pewne kręcenie bitów w celu uzyskania wyjściowego ASCII. Odcinam okrężnicę po ostatniej grupie małym hakiem. Syntezuje i wydaje się działać dla xc3s500e-4ft256-4 na ISE 13.7 lin64.
źródło
C, 91-126 bajtów
Moja oryginalna wersja, 119 bajtów.
Najlepsza przenośna wersja gry w golfa, 103 bajty (dzięki @Dennis za niektóre z tych koncepcji)
Objaśnienie: Sam algorytm jest dość prosty. Użyłem dłuższego niż bez znaku int, ponieważ jest krótszy. Zadeklarowanie ich na poziomie pliku oznacza, że wszystko jest wstępnie zainicjowane zerami. Ta
f
funkcja jest prostym przyrostem z przeniesieniem, który działa na niskich 16 bitach każdego słowa. Pętla kończy się, gdy przenosi się na 129-ty bit.Iteracja wsteczna dla printf oznacza, że drukujemy adresy w „właściwej” kolejności, a także kontrola drukowania nowego wiersza jest krótsza o kilka znaków.
Wykorzystuje to niektóre nieprzenośne konstrukcje. Najlepiej jest traktować go jako dialekt K&R, ponieważ używa niejawnych typów zwrotów int i nie obejmuje stdio.h. I moje użycie longa zostało o tym poinformowane - w większości nowoczesnych systemów int jest wystarczający, ponieważ ma 32 bity. Prawdopodobnie mogłoby to działać niezmodyfikowane na PDP-11 Unix.
Może być jednak krótszy. Jeśli założymy, że możemy użyć int (jako typu szerszego niż 16 bitów lub typu dokładnie 16 bitów o różnych właściwościach, które są prawdziwe w wielu systemach, takich jak dopełnianie dwójki i przewijanie arytmetyczne), możemy pozbyć się rzeczy związane z używaniem długiego.
Wersja dla int szerszych niż 16 bitów, 97 bajtów.
Wersja dla systemów 16-bitowych, 91 bajtów.
Co dziwne, oryginalny kompilator K&R tak naprawdę nie obsługiwał deklaracji bez int (kompiluje się dobrze, ale traktuje zmienne jako zewnętrzne i dlatego nieokreślone w czasie łączenia), więc potrzebne są dodatkowe trzy bajty, aby zmienić deklarację
int*p,a[9];
na w sumie 94.Ponadto, jeśli założenie, że zostało przerwane przed zakończeniem produkcji, było twardym ograniczeniem, moglibyśmy usunąć kontrolę końcową, oszczędzając pięć bajtów.
Bonus: w pełni przenośna wersja ANSI, 126 bajtów:
Nowe wiersze we wszystkich wersjach są wstawiane w celu zapewnienia czytelności oraz w miejscach, w których białe znaki nie są wymagane, i są wykluczane z liczby bajtów, z wyjątkiem nowej linii po
#include
wierszu w wersji ANSI.Wszystkie wersje oprócz wersji ANSI wypadają na końcu main i dlatego mogą zwrócić fałszywy kod wyjścia do systemu operacyjnego.
źródło
a[9];f(int*x){if(++*x>>16)*x=f(x+1);}main(i){for(;!a[8];f(a))for(i=8;i--;)printf(i?"%x:":"%x\n",a[i]);}
i--
sprawdzeniu stanu.a[0]
i zawińa[1]
AutoIt3,
142231 bajtówWyjaśnienie
For $a=0 To 2^32-1
: Iteruj 4 razy ponad 0-2 ^ 32 ((2 ^ 32) ^ 4 = 2 ^ 128) możliwych kombinacji.$s=StringFormat("%08x%08x%08x%08x",$a,$b,$c,$d)
: Konwertuj liczby na ciąg szesnastkowy o długości 32 (4 * 32).For $j=0 To 8
: Iteruj po wszystkich 8 sekcjach łańcucha.ConsoleWrite(StringMid($s,$j*4+1,4)&($j<7?":":""))
: Wyodrębnij 4 kolejne znaki z ciągu i dodaj dwukropek (:
) na końcu, jeśli nie dotarliśmy do ostatniej sekcji, a następnie wyślij wszystko do konsoliNext
: Zakończ wewnętrzną pętlę forConsoleWrite(@LF)
: Dodaj znak końca wiersza na końcu wierszaNext
: Zakończ zewnętrzne pętle forOczekiwany rozmiar wyjściowy: (jedna linia (39 bajtów) + przesunięcie linii) (= 40 bajtów) * 2 ^ 128 = 1,361 * 10 ^ 16 YB (yottabajtów)
źródło
4^64 - 1
?Guma cynamonowa, 16 bajtów
Wypróbuj online. (TIO ogranicza moc wyjściową)
Wyjaśnienie
g
Stawia tryb Cinnamon Gum w tryb generowania . Reszta ciągu dekompresuje się do tego wyrażenia regularnego:Następnie tworzy generator wszystkich możliwych ciągów pasujących do wyrażenia regularnego i przechodzi przez niego, drukując każdy z nich.
Nieco zabawnie, regex golfisty
([0-9a-f]{4,4}:){7,7}[0-9a-f]{4,4}
faktycznie kompresuje się do dłuższego łańcucha niż regex powyżej.źródło
Commodore BASIC 2.0, 339 bajtów
Aby uzyskać małe cyfry szesnastkowe, program jest napisany w „trybie przesuniętym” (naciśnij
<SHIFT>+<C=>
)Samo wykonanie tej pracy na Commodore 64 było wyzwaniem ze względu na pamięć, rozmiar ekranu, rozmiar danych i inne ograniczenia. Zastanawiałem się nad implementacją skróconej reprezentacji, ale inne ograniczenia (takie jak nieudokumentowana niemożność użycia elementów tablicy jako indeksów pętli) oznaczały, że zwiększyłoby to długość programu o około 1000 bajtów.
Linia 7 jest implementacją
HEX$()
, której brakuje Commodore BASIC 2.0. Nie mogę użyćDEF FN
do tego, ponieważ mogą one zwracać tylko liczby, a nie ciągi znaków. Wiersz 6 to podprogram, który stosuje go do grupy czterech cyfr, która byłaby znacznie krótsza, gdyby funkcje mogły zwracać ciągi.Linie 2 i 5 to osiem zagnieżdżonych pętli, zaimplementowanych jako siedem pętli „for” i warunkowe goto, ponieważ osiem pętli „for”, w połączeniu z dwoma „gosubami” do drukowania adresu, przepełni maleńki stos C64.
C64 może drukować około 1,2 adresów na sekundę, przy szacowanym czasie działania 1,3 * 10 ^ 31 lat.
źródło
PowerShell (v4),
193 166 162 145103 bajtówWersja bez premii TimmyD o wielkości 103 bajtów:
Poprzednia wersja z premią przy 145 * 0,8 = 116 bajtów
Z pomocą TimmyD i tomkandy , którzy to podkreślają,
0 -eq $false
ale([bigint]0) -eq $true
. Więc wszystkie moje poprzednie wersje się nie kończą.Poprzednio w wersji 162, przed kilkoma zmianami wyrażeń regularnych:
„Wyzwanie, w którym PowerShell powinien być dość konkurencyjny!” - ja, zanim spróbowałem.
Wyjaśnienie
źródło
for($g=[bigint]::pow(2,128);$g;$g-=1){'{0:X32}'-f$g-replace'(?=(.{4})+$)',':'-replace'^0+:',''}
for($g=[bigint]::pow(2,120);$g;$g-=1){'{0:X32}'-f$g-replace'(?=(.{4})+$)',':'-replace'^0*:',''}
for($g=[bigint]::pow(2,128);$g-gt0;$g-=1){'{0:X32}'-f$g-replace'(?=(.{4})+$)',':'-replace'^\d*:',''}
Tak, pierwszy adres jest nieprawidłowy, ale nie jest powtarzany na końcu. Zauważ też, żewhile($i)
u ciebie nie zatrzyma się na zero -[boolean][bigint]0
ocenia jako prawda0:
już wiodących : /)$i=[bigint]::Pow(4,64);while($i-gt0){('{0:X32}'-f($i-=1)-replace'0(?=.{32})'-replace'.{4}(?!$)','$0:')}
przy 103 ...AutoIt3, 137 bajtów
źródło
4^64 - 1
?Python 2, 95 bajtów
Po prostu przechodzi przez każdą liczbę od 0 do 2 ^ 128. Najpierw konwertuje bieżącą liczbę na ciąg szesnastkowy, a następnie usuwa dane podane przez
'0x'
tę funkcję. Następnie dopasowuje ciąg znaków, tak aby miał 32 zera z przodu, a następnie dzieli go na cztery grupy. W końcu łączy cztery grupy z dwukropkami, drukuje je i dodaje 1 do bieżącej liczby. Ma dodatkową premię, że możesz ją uruchomić od dowolnej wartości, jeśli ją dasz, ale nie potrzebujesz żadnych danych wejściowych.źródło
Haskell 111
Dzięki własnej funkcji sekwencji
s
nie przecieka już pamięć, ale nie czuję się już golfem.źródło
CBM BASIC v7.0 (166 znaków)
Odpowiedź Marka dotyczy BASIC 2.0 Commodore 64, który nie ma wbudowanego polecenia drukowania liczb w systemie szesnastkowym. Jednak dzięki
HEX$()
funkcji w BASIC 7.0 wersja Commodore 128 jest znacznie krótsza. Nie mieści się w jednej linii logicznej (która w C128 jest ograniczona do 160 znaków), ale nadal może być wprowadzana jako dwie osobne linie w trybie bezpośrednim.źródło
Ruby 75
Jest to rozwiązanie rekurencyjne, które pobiera każdy prefiks i znajduje każdy możliwy sufiks. Rekurencyjnie.
źródło
x=->s,n{...};x['',8]
Tcl
341318301źródło