Piękna szuflada z wzorem
Dzień dobry PPCG!
Pewnego dnia, gdy próbowałem pomóc komuś z Stack Overflow, część jego problemu dała mi pomysł na to wyzwanie.
Przede wszystkim sprawdź następujący kształt:
Gdzie wszystkie czarne liczby są indeksem punktów w kształcie, a wszystkie ciemnoniebieskie liczby są indeksem połączeń między punktami.
Teraz, biorąc pod uwagę liczbę szesnastkową od 0x00000 do 0xFFFFF, musisz narysować kształt w konsoli, używając tylko przestrzeni znaków i „■” (użycie znaku „o” jest również w porządku).
Oto kilka przykładów, w których wprowadzana jest liczba szesnastkowa, a kształt jest generowany:
0xE0C25 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
0xC1043 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■
■
■
■
■
■
■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE4F27 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xF1957 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xD0C67 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0x95E30 :
■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■
0x95622 :
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■
■
■
■ ■ ■ ■ ■
0xC5463 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE5975 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xB5E75 :
■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xF4C75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xF5D75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
Oto kilka wyjaśnień na temat tego, jak to działa:
0xFFFFF(16) = 1111 1111 1111 1111 1111(2)
Masz tutaj 20 bitów, każdy bit mówi, czy istnieje link, czy nie.
Indeks najbardziej znaczącego bitu (MSB) wynosi 0 (odniesienie do obrazka) lub mniej znaczący bit (LSB) wynosi 19 (ponownie odniesienie do obrazka).
Oto jak to działa dla pierwszego kształtu podanego jako przykład:
0xE0C25(16) = 1110 0000 1100 0010 0101(2)
Oznacza to, że będziesz mieć następujące istniejące linki: 0,1,2,8,9,9,14,17,19.
Jeśli podświetlisz linie na obrazie referencyjnym tymi liczbami, uzyskasz następujący kształt:
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
Oto prosta i niestosowana implementacja Pythona, jeśli potrzebujesz dodatkowej pomocy:
patterns = [
0xE0C25, 0xC1043, 0xE4F27, 0xF1957,
0xD0C67, 0x95E30, 0x95622, 0xC5463,
0xE5975, 0xB5E75, 0xF4C75, 0xF5D75
]
def printIfTrue(condition, text = "■ "):
if condition:
print(text, end="")
else:
print(" "*len(text), end="")
def orOnList(cube, indexes):
return (sum([cube[i] for i in indexes]) > 0)
def printPattern(pattern):
cube = [True if n == "1" else False for n in str(bin(pattern))[2::]]
for y in range(9):
if y == 0: printIfTrue(orOnList(cube, [0, 2, 3]))
if y == 4: printIfTrue(orOnList(cube, [2, 4, 9, 11, 12]))
if y == 8: printIfTrue(orOnList(cube, [11, 13, 18]))
if y in [0, 4, 8]:
printIfTrue(cube[int((y / 4) + (y * 2))], "■ ■ ■ ")
if y == 0: printIfTrue(orOnList(cube, [0, 1, 4, 5, 6]))
if y == 4: printIfTrue(orOnList(cube, [3, 5, 7, 9, 10, 13, 14, 15]))
if y == 8: printIfTrue(orOnList(cube, [12, 14, 16, 18, 19]))
printIfTrue(cube[int((y / 4) + (y * 2)) + 1], "■ ■ ■ ")
elif y in [1, 5]:
for i in range(7):
if i in [2, 5]:
print(" ", end=" ")
printIfTrue(cube[y * 2 + (1 - (y % 5)) + i])
elif y in [2, 6]:
for i in range(5):
if i in [1, 2, 3, 4]:
print(" ", end=" ")
if i in [1, 3]:
if i == 1 and y == 2:
printIfTrue(orOnList(cube, [3, 4]))
elif i == 3 and y == 2:
printIfTrue(orOnList(cube, [6, 7]))
if i == 1 and y == 6:
printIfTrue(orOnList(cube, [12, 13]))
elif i == 3 and y == 6:
printIfTrue(orOnList(cube, [15, 16]))
else:
printIfTrue(cube[(y * 2 - (1 if y == 6 else 2)) + i + int(i / 4 * 2)])
elif y in [3, 7]:
for i in range(7):
if i in [2, 5]:
print(" ", end="")
ri, swap = (y * 2 - 2) + (1 - (y % 5)) + i, [[3, 6, 12, 15], [4, 7, 13, 16]]
if ri in swap[0]: ri = swap[1][swap[0].index(ri)]
elif ri in swap[1]: ri = swap[0][swap[1].index(ri)]
printIfTrue(cube[ri])
if y == 0: printIfTrue(orOnList(cube, [1, 7, 8]))
if y == 4: printIfTrue(orOnList(cube, [6, 8, 10, 16, 17]))
if y == 8: printIfTrue(orOnList(cube, [15, 17, 19]))
print()
for pattern in patterns:
printPattern(pattern)
Oczywiście nie jest idealny i dość długo czeka na to, co powinien zrobić, i właśnie dlatego tu jesteś!
Co sprawia, że ten program jest absurdalnie krótki :)
To jest golf golfowy, więc wygrywa najkrótsza odpowiedź!
źródło
Odpowiedzi:
JavaScript (ES6),
202188187 bajtówJak to działa
Pracujemy na siatce
g
9 rzędów po 10 znaków. Siatka jest początkowo wypełniona spacjami, a LineFeed co 10 znak.Każdy segment jest określony przez pozycję początkową i kierunek.
Wskazówki są kodowane w następujący sposób:
Każdy segment jest zakodowany jako liczba całkowita:
Na przykład segment # 3 zaczyna się w pozycji 55 i używa trzeciego kierunku. Dlatego jest zakodowany jako
(55 << 2) | 3 == 223
.Poniżej znajduje się wynikowa lista liczb całkowitych, od segmentu 19 do segmentu 0:
Po zakodowaniu w delcie, począwszy od 356, staje się:
Który jest ostatecznie zakodowany jako:
źródło
Python 3, 289 bajtów
Nic mądrego, tylko twarde kodowanie.
źródło
"trq|t...a|eca".split("|")
się stać"tqr t...a eca".split()
?.split()
niszczy||
.Rubin, 116 bajtów
Opiera się to na kilku wzorach, które zaobserwowałem. Po pierwsze, wzór powtarza się co 9 linii. Po drugie, jeśli punkty początkowe linii poziomych są odpowiednio wybrane, kierunki x zmieniają się w sposób ciągły przez prawą, lewą i prostą.
Niegolfowany w programie testowym
Wydaje mi się, że istnieje rozwiązanie 112-bajtowe wykorzystujące ciąg 20 znaków i dekodowanie w celu zdefiniowania parametrów 20 linii. Spróbuję później, jeśli będę miał czas.
źródło
PHP,
142150149 bajtówdrukuje kształt w miarę potrzeby; tzn. jeśli dolna część jest pusta, zostanie wycięta.
Uruchom z
php -nr '<code>' <input>
. Nie wpisuj prefiksuPrzetestuj online
Dodaj 11 bajtów, aby nie ciąć: wstaw
,$r[80]=" "
po$r=""
.wyjaśnienie kodowania
Każda linia może być opisana punktem początkowym i jednym z czterech kierunków.
Rysując na siatce 9x9, pozycja początkowa waha się od
0,0
do8,4
; lub łącznie, od0
do8*9+4=76
. Na szczęście wszystkie punkty początkowe[0,4,8,36,40,44,72,76]
są podzielne przez 4; więc kod kierunku[0..3]
można wycisnąć na bity 0 i 1 -> nie trzeba w ogóle przesuwać.W celu łatwego obliczenia ruchu kursora
0
przyjmuje się dla wschodu (tylko kierunek bez ruchu pionowego) i[1,2,3]
dla południowo-zachodniej, południowej, południowo-wschodniej, gdzie przesunięcie wynosi9
(dla ruchu pionowego) plus[-1,0,1]
->[8,9,10]
->delta=code?code+7:1
.Kierunek dla pierwszej i ostatniej linii jest wschodni, co skutkuje kodami w zakresie od 0 do 76
[0+0,4+0,0+2,0+3,4+1,4+2,4+3,8+1,8+2,...,44+1,44+2,72+0,76+0]
; i bitowa xor 96 dla każdej wartości powoduje wydrukowanie i bezproblemowych kodów ascii[96,100,98,99,101,102,103,105,106,68, 72,70,71,73,74,75,77,78,40,44]
->`dbcefgijDHFGIJKMN(,
. Kod używa LSB dla bitu 0, podczas gdy linia 0 odpowiada MSB, więc ciąg musi zostać odwrócony. Finito.awaria
wyjaśniono niektóre gry w golfa
^96
nie ma wpływu na dolne dwa bity, można go zignorować podczas wydobywania kierunku; więc nie ma potrzeby przechowywania wartości w zmiennej, która zapisuje 5 bajtów na init kursora.~3
zamiast124
oszczędza jeden bajt i pozwala na następne granie w golfa:$k=3
wewnątrz$p
przydziału pozwala zaoszczędzić dwa bajtyi nie zaszkodzi warunkowi wstępnemu (ponieważ górna wartość nadal ma jedną cyfrę).
chunk_split
jest najkrótszym sposobem wstawienia podziałów linii.Nie chcę nawet wiedzieć, o ile więcej by coś zabrało.
7+($c&3?:-6)
jest o jeden bajt krótszy niż$c&3?$c%4+7:1
.hexdec()
(8 bajtów), aby spełnić ograniczenie wejściowe.źródło
JavaScript,
184183178168167 bajtówPoczątkowo miał 206 bajtów, ale odpowiedź @ Arnaulda zainspirowała mnie do zbadania jednowymiarowego rozwiązania tablicowego. Edycja: Zapisano 1 bajt dzięki @ edc65. Zaoszczędź
515 bajtów dzięki @Arnauld. Zapisano kolejny bajt, modyfikując wybór znaków.źródło
[0,1,2,3,4]
jest krótszy[67,65,52,36,51,50,34,49,48,35,33,20,4,19,18,2,17,16,3,1]
i[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o')
[..."ecVFUTDSREC6&54$32%#"]
i,[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o',e=e.charCodeAt()-34)
aby zaoszczędzić 10 dodatkowych bajtów.~
zamiast-34
(niestety nie zgadzam się z `\ ', dlatego nie oszczędzam 2 bajtów).Partia, 491 bajtów
Uwaga: ostatni wiersz kończy się spacją. Umieszczenie
if
warunku ze zmienną wfor
pętli jest poza partią, więc wymaga własnego podprogramu. Ponieważ nic nie robi, wpadam do środka, by wyjść. Bez~
cudzysłowu ciągi w zewnętrznej pętli pozwalają pętli wewnętrznej na zapętlanie liczb. Liczby są po prostu maskami bitowymi dla wszystkich miejsc, w którycho
należy narysować s.źródło
C,
267262260256 znakówLiczenie ucieka jako 1 znak
k to odnośnik, do których pól należy wstawić „o”.
Wypróbuj online!
źródło
Befunge, 468 bajtów
Wypróbuj online!
Pierwszy wiersz odczytuje ciąg ze standardowego wejścia, oceniając go jako liczbę szesnastkową. Reszta kodu to w zasadzie podwójna pętla nad współrzędnymi x / y siatki, z masywnym obliczeniem logicznym określającym, czy
o
należy wyprowadzić dla każdej lokalizacji.Zasadniczo istnieje osobny warunek dla każdego z 20 punktów siatki, na przykład (pierwsze cztery):
A potem, kiedy obliczyliśmy wszystkie 20, razem LUB dużo razem, i jeśli ten wynik jest prawdziwy, wyprowadzamy a
o
, w przeciwnym razie wyprowadzamy spację.Befunge nie ma żadnych przeszkód w operacjach na bitach, więc aby wydobyć bity z danych wejściowych, po prostu ciągle ewaluujemy,
n%2
a następnien/=2
przechodzimy przez 20 obliczeń warunków.źródło