Liczenie Quipu: Baza 10 w Nowym Świecie

41

Quipus to starożytne urządzenie używane przez Inków w epoce prekolumbijskiej do rejestrowania liczb w podstawowym systemie pozycjonowania węzłów na sznurze, który działa w następujący sposób:

Każda wiązka węzłów jest cyfrą i istnieją trzy główne typy węzłów: proste węzły odręczne; „długie węzły”, składające się z supełka z jednym lub więcej dodatkowymi zwojami; i węzły ósemkowe.

  • Siły dziesięciu są pokazane według pozycji wzdłuż sznurka, a ta pozycja jest wyrównana między kolejnymi pasmami.
  • Cyfry w pozycjach dla mocy 10 i wyższych są reprezentowane przez skupiska prostych węzłów (np. 40 to cztery proste węzły z rzędu w pozycji „dziesiątek”).
  • Cyfry w pozycji „jedynki” są reprezentowane przez długie węzły (np. 4 to węzeł z czterema zwojami). Ze względu na sposób wiązania węzłów cyfra 1 nie może być pokazana w ten sposób i jest reprezentowana w tej pozycji przez ósemkowy węzeł.
  • Zero jest reprezentowane przez brak węzła w odpowiedniej pozycji.

Detale

Na to wyzwanie, każda nić Quipu reprezentuje pojedynczy numer (choć, jak mówi artykuł w Wikipedii, to może reprezentować wiele liczb na jednej nici, w tym wyzwaniem, nie będziemy).

Sęki

Każdy węzeł będzie reprezentowany przez pojedynczy znak ASCII.

  • . reprezentuje prosty węzeł
  • : reprezentuje jeden obrót długiego węzła
  • 8 przedstawia węzeł ósemkowy
  • | oznacza brak węzła, a także separatora między cyframi.

Konstruowanie Quipusa

Quipu buduje się zgodnie z tymi zasadami.

  1. Nici biegną od góry do dołu w malejącej kolejności pozycji (jak w, cyfra jednostek będzie na dolnym końcu nici). Cyfry wzdłuż nici są oddzielone znakiem ( |).
  2. Moc 10 cyfr reprezentowana jest przez jej położenie wzdłuż pasma w taki sam sposób, w jaki moc cyfry 10 byłaby obliczana przy użyciu jej indeksu w liczbach w naszym systemie liczbowym. Oznacza to, że 24ze znakiem 2dziesiątek i miejscem 4jednostek będą reprezentowane przez dwa węzły, separator ( |), a następnie cztery węzły.
  3. Cyfry w tej samej pozycji są wyrównane w kierunku dolnej części pasma. Jeśli jedna cyfra na pozycji będzie miała mniej węzłów niż inne cyfry innych liczb na tej samej pozycji, brak tych węzłów jest reprezentowany przez ( |).
  4. Kolejne proste węzły ( .) reprezentują wartość w ich położeniu.
  5. Każda cyfra jest reprezentowana przez co najmniej 1 znak. Gdy wartość cyfr wynosi 0 dla wszystkich liczb w quipu, jest reprezentowana przez brak węzła ( |).
  6. Miejsce jednostek jest traktowane specjalnie. Jeden w miejscu jednostek jest reprezentowany przez węzeł ósemkowy ( 8). Wartość dwóch lub więcej w miejscu jednostek jest reprezentowana przez kolejne długie węzły ( :).
  7. Kiedy cyfra jednostek wynosi 0 dla wszystkich liczb w quipu, brak węzła nie jest drukowany, ale ogranicznik końcowy dla cyfry dziesiątek zostaje zachowany.
  8. Po cyfrze jednostek nie ma separatora.

Zasady

  • Dane wejściowe będą składały się z niepustej listy liczb całkowitych nieujemnych, które można otrzymać dowolną domyślną metodą wprowadzania . Możesz założyć, że te liczby całkowite są mniejsze lub równe 2147483647lub 2^31-1. Podczas gdy przypadki testowe są rozdzielane spacjami, format wejściowy może rozdzielać dane wejściowe w dowolny sposób dogodny dla Twojego języka, niezależnie od tego, czy są one rozdzielane przecinkami, rozdzielane znakiem nowej linii, w tablicy i tak dalej.
  • Wyjście składa się z pojedynczego Quipu zbudowanego zgodnie z zasadami opisanymi powyżej. Dane wyjściowe można podać za pomocą dowolnej domyślnej metody wyjściowej .
  • Kod powinien być programem lub funkcją, chociaż nie musi to być funkcja nazwana.
  • Węzły zajmują trochę czasu, więc aby zaoszczędzić czas, twój kod powinien być jak najkrótszy.

Jak zawsze, jeśli problem jest niejasny, daj mi znać. Powodzenia i dobrej gry w golfa!

Przykłady

Wejście:

5 3 1 0

Wynik:

:|||
:|||
::||
::||
::8|

Wejście:

50 30 10 0

Wynik:

.|||
.|||
..||
..||
...|
||||

Wejście:

330

Wynik:

.
.
.
|
.
.
.
|

Wejście:

204 1

Wynik:

.|
.|
||
||
||
:|
:|
:|
:8

Wejście:

201 0 100 222

Wynik:

.||.
.|..
||||
|||.
|||.
||||
|||:
8||:

Wejście:

1073741823 2147483647

Wynik:

|.
..
||
|.
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
..
||
|.
|.
..
||
.|
.|
..
..
..
..
..
..
||
|.
|.
..
..
||
|:
|:
|:
|:
::
::
::

Wejście:

0

Wynik:

|

Dłuższe przypadki testowe

Dalsza lektura

Sherlock9
źródło

Odpowiedzi:

3

Pyth, 64 bajty

=QjRTQjCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

Wypróbuj online!

Jak to działa

=QjRTQ   Converts each number in input to decimal (as a list)
         123 becomes [1,2,3]

----

jCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

                                              .[L0       Q  0-leftpad each #
                                                  h.MZlMQ   (max length) times

                                             C              transpose

                      mm                    d    for each digit:
                        +                        [convert to] sum of
                         *\|                     "|" repeated
                            -                    the difference of
                             h.MZd               maximum digit in same row
                                  k              and itself.. that many times
                                   *?tk\:\8      and (digit > 1 then ":" or "8") repeated
                                           k     itself many times


the list:
[11,23,52]
->[[1,1],[2,3],[5,2]]
->[[1,2,5],[1,3,2]]
->[["||||8","|||::",":::::"],["||8",":::","|::"]]

                     C      transpose

->[["||||8","||8"],["|||::",":::"],[":::::","|::"]]

  m                          for each number
      +                      [convert to] sum of
                 Pd          every element but the last
       :R"[8:]"\.            with "8" and ":" replaced by "."
                   ed        and the last element
   j\|                       joined with "|"

  C                          transpose
 j                           join (with newlines)
Leaky Nun
źródło
To doskonała odpowiedź, z wyjątkiem jednego problemu. Ostatnim węzłem nie zawsze jest węzeł ósemkowy 8. W rzeczywistości jest to tylko 8węzeł, gdy ostatnia cyfra to 1 (patrz reguła 6). Konwertujesz wszystkie końcowe węzły, a to nie pasuje do specyfikacji. Również wypróbuj online! link ma inny kod niż ten, który tutaj opublikowano, najwyraźniej
Sherlock9
22

Nieczytelny , 3183 3001 bajtów

To było zabawne wyzwanie, aby popracować między świętami Bożego Narodzenia. Dziękujemy za wysłanie wiadomości! Gra w golfa była interesująca, ponieważ specyfikacja jest pełna wyjątków i specjalnych przypadków, które wymagały wielu warunków if. Ponadto, chociaż tym razem nie musiałem konwertować na i od dziesiętnego, potrzebowałem rodzaju „max”, aby określić największą liczbę cyfr w każdej liczbie i największą wartość cyfr w każdym miejscu.

Pierwsza wersja tego pliku to 4844 bajty, aby dać wyobrażenie o tym, ile grałem w golfa.

Program oczekuje danych wejściowych jako rozdzielonej przecinkami listy liczb całkowitych. Bez spacji i znaków nowej linii. Korzystanie z nich spowoduje niezdefiniowane zachowanie.

„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ „” „„ ” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ” „” „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „„ ” „„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „„ ” „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „„ ” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „„ ”„ ”„ „” „” „” „” „” „” „„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ „” „” „”„” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ „” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ „ „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ „” „” „” „”„” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „„ ”„ ”„ ”„ ”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ” „” „” „” „” „” „” „” „„ ”„ ”„ „” „„ ”„ „” „” „” „„ ”„ ”„ ” „” „” „” „” „” „” „„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ „” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „”„” „” „” „” „” „„ ”„ „” „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „„ ”„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ” „” „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ „” „” „”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „” „” „„ ”„ „” „„ ”„ ”„ „” „” „”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ „” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ „” „” „”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „„ ” „” „„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „„ ” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „„ ”„ ”„ ”„ ”„” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „ „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „”„” „” „” „” „„ ”„ „” „” „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „„ ”„ ”„ „” „” „” „” „„ ”„ „” „„ ”„ ”„ ” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „„ ” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”

Wyjaśnienie

Pokażę ci, jak działa program, pokazując, jak przetwarza określone dane wejściowe 202,100,1.

Na początku konstruujemy kilka wartości, które będą nam potrzebne później - głównie kody ASCII znaków, które wyprowadzimy.

wprowadź opis zdjęcia tutaj

Jak widać '8'i '.'są już dostępne. '|', jednak tak naprawdę wynosi 124, a nie 14. Używamy pętli while, aby dodać dwukrotnie wartość tymczasową w gnieździe nr 1, aby uzyskać 124 (czyli 14 + 55 × 2, ponieważ pętla while działa dla 56-1 = 55 iteracje). Oszczędza to niektóre bajty, ponieważ duże literały całkowite, takie jak 124, są naprawdę długie. Na poniższym diagramie pokazuję lokalizację każdej zmiennej używanej przez program.

wprowadź opis zdjęcia tutaj

Następnie chcemy wprowadzić wszystkie znaki i zapisać je na taśmie, zaczynając od komórki nr 12 ( p jest do tego wskaźnikiem uruchomionym). Jednocześnie chcemy wiedzieć, jak najdłuższa jest liczba (ile cyfr). Aby to osiągnąć, utrzymujemy sumę bieżącą w jednostajnym ruchu w lewo, zaczynając od komórki # -1 (używamy q jako wskaźnika). Po pierwszej liczbie wejściowej ( 202) taśma wygląda teraz tak:

wprowadź opis zdjęcia tutaj

Zauważysz, że liczby są wyłączone o 4. Cóż, kiedy je wprowadzamy, są to ich wartości ASCII, więc są „wyłączone” o 48, a przecinek wynosi 44. Dla każdego znaku kopiujemy 46 z '.'do r, a następnie odejmij go za pomocą pętli while (która odejmuje 45), a następnie dodajemy 1. Robimy to, aby przecinek (nasz separator) wynosił 0, więc możemy użyć warunkowego rozpoznania go.

Zauważysz również, że zostawiamy komórkę nr 11 na 0. Potrzebujemy tego, aby rozpoznać granicę pierwszej liczby.

Następną postacią będzie przecinek, więc przechowujemy 0 na # 15, ale oczywiście tym razem nie przesuwamy q . Zamiast tego ustawiamy q z powrotem na 0 i zaczynamy „nadpisywać” jedynki, które już umieściliśmy.

Po przetworzeniu wszystkich pozostałych znaków otrzymujemy:

wprowadź opis zdjęcia tutaj

Jak widać, cyfry 1 napisane przez q wskazują teraz (w unary) długość najdłuższej liczby.

Teraz używamy pętli while, aby przesunąć q na samą lewą stronę, a następnie umieścić tam inny wskaźnik, który nazwiemy r2 . Cel r2 stanie się jasny później.

wprowadź opis zdjęcia tutaj

W tym miejscu pozwól mi wyjaśnić terminologię, której będę używać w tym miejscu.

  • Przez liczbę rozumiem jedną z liczb wejściowych oddzielonych przecinkami. W naszym przykładzie są to 202, 100 i 1.
  • Przez cyfrę rozumiem pojedynczą cyfrę w określonej z liczb. Pierwszy numer ma 3 cyfry.
  • Przez miejsce rozumiem jedno miejsce, dziesiątki miejsca, setki miejsc itp. Więc jeśli powiem „cyfry w bieżącym miejscu”, a bieżące miejsce to jedyne miejsce, cyfry to 2, 0 i 1 w tym miejscu zamówienie.

Teraz wracamy do naszego regularnego programowania. Cała reszta programu to duża pętla, która przesuwa q do przodu, aż osiągnie komórkę # 0. Każda z komórek po drodze reprezentuje miejsce, z tymi po skrajnie prawej stronie, a q rozpocznie się od najbardziej znaczącego. W naszym przykładzie jest to setki miejsc.

Kontynuujemy, zwiększając liczbę punktów q w komórce (czyli * q ).

wprowadź opis zdjęcia tutaj

Jesteśmy teraz na „etapie 2” dla setek miejsc. Na tym etapie dowiemy się, jaka jest największa cyfra spośród wszystkich cyfr w setkach miejsc. Używamy do tego tej samej jednostkowej sztuczki liczenia, z tym wyjątkiem, że wskaźnik nazywa się r, a wskaźnik r2 oznacza jego pozycję początkową, do której musimy go resetować za każdym razem, gdy przechodzimy do następnej liczby.

Zacznijmy od pierwszego numeru. Zaczynamy od ustawienia p na 11 (zakodowana pozycja początkowa wszystkich liczb). Następnie używamy pętli while, aby znaleźć koniec liczby i ustawiamy tam p2 , aby zaznaczyć pozycję. Jednocześnie ustawiamy q2 na 0:

wprowadź opis zdjęcia tutaj

Nie rozpraszaj się faktem, że q2 wskazuje na zmienne. Nie mamy tam wypełnienia pustej komórki, ponieważ możemy wykryć komórkę 0 po prostu dlatego, że jest to zero.

Następnie przeglądamy bieżącą liczbę, zmniejszając jednocześnie p i q2,* p wyniesie zero. W każdym miejscu wartość * q2 mówi nam, co musimy zrobić. 1 oznacza „nic nie rób”, więc kontynuujemy. W końcu napotykamy 2 w komórce # −3. Za każdym razem, gdy * q2 nie jest równe 1, q2 jest zawsze równe q .

wprowadź opis zdjęcia tutaj

Jak już wspomniałem, etap 2 to „określenie największej cyfry w tym miejscu”. Więc ustawiamy r na r2 , używamy pętli while, aby zmniejszać * p i przesuwamy r w lewo i wypełniamy taśmę 1s, a następnie używamy kolejnej pętli while, aby przesuwać r z powrotem w prawo i zwiększać * p ponownie, aby przywrócić wartość. Pamiętaj, że pętla co chwilę działa dla jednej iteracji mniej niż wartość, na której ją używamy; z tego powodu liczba zapisanych 1s będzie o 3 więcej (zamiast 4 więcej) niż wartość cyfr, a końcowa wartość przechowywana z powrotem w * p będzie o 2 więcej. W ten sposób skutecznie zmniejszono * p o 2.

Następnie ustawiamy p na wartość p2, a następnie robimy to wszystko ponownie. Po raz drugi ustaw q2 na 0, znajdź koniec numeru, przesuwając p w prawo, a następnie przejdź przez cyfry tego numeru, zmniejszając jednocześnie p i q2 . Po raz kolejny napotkamy 2 w komórce # −3 i napiszemy tyle 1s z * r .

W przypadku trzeciej liczby nie robimy nic, ponieważ nie ma setek miejsc (więc q2 nigdy nie osiąga q ), ale to jest w porządku, ponieważ nie wpływa to na obliczenie maksymalnej wartości cyfr.

wprowadź opis zdjęcia tutaj

Ustawiliśmy również komórkę * (r - 4) , którą zaznaczyłem tutaj nieoznaczoną strzałką, na 1 (mimo że jest już na 1). Nie powiem ci jeszcze dlaczego, ale może już zgadłeś?

Następny przyrost * q przenosi nas do etapu 3, czyli „odejmij cyfrę maksymalną od wszystkich cyfr w bieżącym miejscu”. Tak jak poprzednio, resetujemy p do 11 i q2 do 0, a następnie przechodzimy przez wszystkie liczby, tak jak zrobiliśmy to w poprzednim etapie; z wyjątkiem tego czasu * q = 3 zamiast 2. Za każdym razem, gdy q2 spotyka q, a p znajduje się w setkach miejsc, używamy pętli while do zmniejszenia * p tyle razy, ile jest 1s w bloku po lewej stronie * r2 (5 w naszym przykładzie) przy użyciu rjako wskaźnik biegu. Faktycznie zmniejszamy go jeszcze raz, aby największa cyfra kończyła się na -2, z powodu, który stanie się później jasny:

wprowadź opis zdjęcia tutaj

Po przetworzeniu wszystkich liczb jesteśmy teraz na końcu etapu 3. Tutaj wykonujemy dwie osobliwe rzeczy.

  • Najpierw odejmujemy również rozmiar bloku r (plus 1) od * q , ale używając wskaźnika r2 , który pozostawia go po lewej stronie. * q staje się w ten sposób ujemny. W naszym przypadku r- blok ma pięć 1, więc * q staje się −3.
  • Po drugie, ustawiamy zmienną na niezerową wartość, aby wskazać, że wchodzimy teraz w etap wyjściowy. (Technicznie fakt, że * q jest ujemny, wskazuje już na stopień wyjściowy, ale jest to zbyt trudne do sprawdzenia, stąd dodatkowa zmienna).

Teraz rozumiesz, że ciągle przeglądamy liczby, znajdujemy bieżące miejsce (wskazane przez wartość inną niż 1 * q ) w obrębie każdej liczby i robimy coś w zależności od wartości * q . Widzimy, że * q jest najpierw zwiększane do 2 (= oblicz maksymalną wartość cyfry), a następnie 3 (odejmuj maksymalną wartość cyfry od każdej cyfry w tym miejscu), a następnie odejmujemy od niej, aby była ujemna. Stamtąd będzie rosnąć, aż osiągnie 1, przywracając w ten sposób wartość oznaczającą „nic nie rób”. W tym momencie przechodzimy do następnego miejsca.

Teraz, gdy * q jest ujemne, wysyłamy dane wyjściowe. * q ma dokładnie prawidłową wartość, dzięki czemu wyprowadzimy odpowiednią liczbę wierszy znaków, zanim osiągnie 1; jeśli największa cyfra to 2, musimy wyprowadzić 3 wiersze. Zobaczmy, co się stanie przy każdej wartości * q :

  • * q = -2:
    • W przypadku pierwszej liczby * p wynosi -2, co oznacza, że ​​musimy wyprowadzić a '.'(kropkę) lub a ':'(dwukropek). Decydujemy, które patrząc na q : jeśli jest to -1, jesteśmy w jednym miejscu, więc wypisz a ':'(które obliczamy jako '8'+2), w przeciwnym razie a '.'.
    • Dla drugiej liczby * p wynosi −3. Wszystko, co nie jest -2 oznacza, że ​​wyprowadzamy '|'(potok), a następnie zwiększamy wartość. W ten sposób osiągnie -2 we właściwym miejscu, a następnie wyprowadzimy '.'s / ':'s dla reszty tej cyfry.
    • W każdym przypadku ustawiamy również zmienną pd na 0 przed przetworzeniem liczby i ustawiamy pd (= „drukowane”) na wartość niezerową, aby wskazać, że wydrukowaliśmy znak.
    • W przypadku trzeciej liczby przetwarzanie nie występuje, ponieważ trzecia liczba nie ma setek miejsc. W tym przypadku pd będzie nadal wynosić 0 po przetworzeniu liczby, co oznacza, że ​​nadal musimy wyprowadzić a '|'(ale tylko wtedy , gdy out jest niezerowy, ponieważ w przeciwnym razie nadal jesteśmy na etapie 2 lub 3).
    • Po przetworzeniu wszystkich liczb, jeśli out jest niezerowy, wypisz nowy wiersz. Zauważ, że potrzebujemy zmiennej out , abyśmy nie wypisywali nowej linii na etapie 2 lub 3.
  • * q = -1: Tak samo jak poprzednio, z tym wyjątkiem, że * p wynosi -2 dla obu pierwszych dwóch liczb, więc oba wyprowadzają a'.'(a trzecie wyprowadza a'|'jak poprzednio).
  • * q = 0: Gdy * q wynosi 0, oznacza to „nic nie rób, jeśli jesteśmy w jednym miejscu, w przeciwnym razie wypisz wiersz'|'s niezależnie od * p ”. W ten sposób uzyskujemy dopełnienie między cyframi.

Teraz zwiększamy q, aby przejść do następnego miejsca, miejsca dziesiątek i zwiększamy * q tam. Na początku drugiego etapu taśma wygląda następująco:

wprowadź opis zdjęcia tutaj

Następnie wykonujemy etap 2 tak jak poprzednio. Pamiętaj, że to skutecznie odejmuje 2 od każdej cyfry w tym miejscu, a także pozostawia niezmienną liczbę pozostawioną z * r2 wskazującą maksymalną cyfrę. Pozostawiamy poprzedni numer jednostkowy w spokoju i po prostu wyciągamy taśmę w lewo; „wyczyszczenie” kosztowałoby tylko niepotrzebny dodatkowy kod. Kiedy skończymy i zwiększamy * q , na początku etapu 3 taśma jest teraz:

wprowadź opis zdjęcia tutaj

Właściwie to kłamstwo. Pamiętasz wcześniej, gdzie powiedziałem, że ustawiliśmy * (r - 4) na 1 i nie powiedziałem ci dlaczego? Teraz powiem ci dlaczego. Dotyczy to przypadków takich jak ten, gdzie największa cyfra to w rzeczywistości 0, co oznacza, że wszystkie cyfry w tym miejscu to 0. Ustawienie * (r - 4) , wskazane przez nieznakowaną strzałkę powyżej, do 1 powoduje zwiększenie liczby jednorzędowej o 1, ale tylko w tym szczególnym przypadku. W ten sposób udajemy, że największą cyfrą jest 1, co oznacza, że ​​wyprowadzimy jeden dodatkowy wiersz.

Po etapie 3 (odejmij cyfrę maksymalną od wszystkich cyfr w bieżącym miejscu), włączając dodatkowy krok, który powoduje, że * q jest ujemny, taśma wygląda następująco. Ostatnim razem najwyższa cyfra była reprezentowana przez −2 w bloku * p , ale tym razem wszystkie są −3, ponieważ w rzeczywistości wszystkie są zerami, ale udajemy, że maksymalna cyfra to 1.

wprowadź opis zdjęcia tutaj

Zobaczmy teraz, co się stanie, gdy * q przejdzie w kierunku 1:

  • Gdy * q = -1, wszystkie * p są równe -3, co oznacza, że ​​wyprowadzamy '|'s i zwiększamy je.
  • Kiedy * q = 0, wyprowadzamy, '|'ponieważ zawsze tak robimy, gdy * q = 0, niezależnie od * p .

W ten sposób otrzymujemy dwa rzędy rur.

Na koniec przenosimy * q na miejsce jednego. Ten staje się interesujący, ponieważ musimy wypisać ':'s, jeśli rzeczywista cyfra jest inna niż 1, ale '8'jeśli to 1. Zobaczmy, jak działa program. Najpierw zwiększamy * q, aby rozpocząć Etap 2:

wprowadź opis zdjęcia tutaj

Po etapie 2 („oblicz maksymalną wartość cyfr”) pozostaje nam to:

wprowadź opis zdjęcia tutaj

Po etapie 3 („odejmij maksymalną wartość cyfr od wszystkich cyfr w bieżącym miejscu”) taśma wygląda następująco:

wprowadź opis zdjęcia tutaj

Teraz przejdźmy kolejno do każdej iteracji * q :

  • * q = -2:
    • Pierwsza liczba: już na -2, więc wypisz a ':'(zamiast a, '.'ponieważ q = -1).
    • Druga liczba: at -4, więc wypisz a '|'i przyrost.
    • Trzecia liczba: przy -3, więc wypisz a '|'. Jednak tym razem zamiast inkrementacji uruchamiany jest specjalny przypadek. Tylko jeśli wyprowadzamy ostatnie miejsce ( q = -1) i znajdujemy się w tym przedostatnim rzędzie ( * q = -2), a cyfra to w rzeczywistości 1 ( * p = -3) , wtedy zamiast zwiększany do -2, że ustawione na -1. Innymi słowy, używamy -1 jako specjalnej wartości, aby wskazać, że w następnej iteracji będziemy musieli wyprowadzać dane '8'zamiast ':'.
  • * q = -1:
    • Pierwsza liczba: już na -2, więc wypisz a ':'.
    • Druga liczba: na -3, więc wyjście A '|'. Warunek specjalny nie jest uruchamiany, ponieważ * q nie jest już równe -2. Dlatego przyrost.
    • Trzecia liczba: at -1, więc wyjście '8'.
  • * q = 0: Zwykle wypisywaliśmy tutaj wiersz wypełnienia'|'s, ale w szczególnym przypadku, gdy jesteśmy w jednym miejscu ( q = -1), pomijamy to.

Następnie q jest zwiększane do 0, a duża pętla while kończy się.

Teraz wiesz, jak 202,100,1działa takie wejście . Jest jednak jeszcze jeden szczególny przypadek, którego jeszcze nie omówiliśmy. Być może pamiętasz, że podczas przetwarzania ostatniego miejsca, gdy * p było −3, ustawiliśmy go na −1 dla 1(zamiast zwiększania do −2), aby następna iteracja wygenerowała '8'zamiast niego. Działa to tylko dlatego, że mamy iterację, w której * p wynosi −3 i podejmujemy decyzję, czy należy ją zwiększyć, czy ustawić na −1. My nie mają takiej iteracji jeśli wszystkie cyfry w miejscu z nich to 0 lub 1. W takim przypadku wszystkie * P wartości dla 1s by zacząć się w -2; nie ma możliwości wyboru ustawienia na -1zamiast zwiększać ją z -3 . Z tego powodu w etapie 3 występuje inny warunek specjalnej obudowy („odejmij maksymalną liczbę od każdej cyfry w bieżącym miejscu”). Twierdziłem, że po odjęciu wartości maksymalnej cyfry od każdej cyfry (w tym momencie cyfra maksymalna wynosi -1), po prostu ją zmniejszamy jeszcze raz, ale tak naprawdę istnieje warunek, który wygląda następująco:

Jeśli cyfra, na którą patrzymy, jest równa maksymalnej cyfrze w tym miejscu ( * p = -1), a to miejsce to jedyne miejsce ( q = -1), a maksymalna cyfra to 1 ( * (r + 5) = 0, tzn. Jednostkowy blok po lewej stronie ma tylko 5 komórek długości, tylko wtedy zostawiamy * p na -1, aby wskazać, że jedyna iteracja wyjścia musi dać an '8'. We wszystkich innych przypadkach ponownie to zmniejszamy.

Gotowy. Szczęśliwego Nowego Roku!

  • Edycja 1 (3183 → 3001): Trochę golfa w Szczęśliwego Nowego Roku! Udało mi się całkowicie pozbyć zmiennych p2 i r2 ! p pędzi teraz w tę iz powrotem, aby znaleźć początek i koniec liczb, ale wydaje się, że kod jest krótszy. Próbowałem również pozbyć się q2 , ale nie mogłem skrócić kodu w ten sposób.

    Znalazłem też kilka innych miejsc, w których mogłem zastosować typowe Nieczytelne sztuczki golfowe, takie jak ponowne użycie ostatniej wartości pętli while. Podam przykład zamiast

    while *(++p) { 1 }         // just increment p until *p is 0; the 1 is a noop
    if (pd) { x } else { y }   // where pd is a variable
    

    Mogę zapisać '""""(zrób pierwszy, potem drugi) i '"""(stałą 1), pisząc to w sposób podobny do

    if (while *(++p) { pd }) { x } else { y }
    

    Oczywiście działa to tylko wtedy, gdy wiem, że pętla while będzie działała przez co najmniej jedną iterację, ale jeśli tak, jej wartością zwracaną jest pd, więc mogę użyć tego jako warunku dla if.

Timwi
źródło
„Nieczytelne” to z pewnością trafna nazwa ...
Alex A.
9
-1 niewystarczające wyjaśnienie
Facet z kapeluszem
7

JavaScript (ES6) 750 744 690 604 498 346 245 234 bajtów

Jestem nowy w PPCG i pomyślałem, że mógłbym spróbować tego, myśląc, że to dość proste. Chłopie się myliłem !! Pracuję nad tym od dłuższego czasu i mam wiele do gry w golfa ...
Sugestie są zachęcane! - chociaż zrozumienie tego nie będzie łatwym zadaniem.

Wysyła liny, gdy dane wejściowe są tablicą liczb (np [204, 1].:).

a=>(o=m=s="",l=a.map(n=>(s+="|",l=(n+"").length)>m?m=l:l),h=[],a=a.map((n,i)=>[..."0".repeat(m-l[i])+n].map((d,j)=>d<h[j]?d:h[j]=d)),h.map((n,i)=>{i?o+=s+`
`:0;for(j=n;j--;o+=`
`)a.map(d=>o+="|.:8"[d[i]-j<1?0:i<m-1?1:d[i]-1?2:3])}),o)

Wyjaśnienie

a=>(

  o=m=s="",                      // m = max number of digits in a number, s = separator string         
  l=a.map(n=>(                   // l = lengths of each number
      s+="|",                    // set the separator string
      l=(n+"").length                 // convert each number to a string
    )>m?m=l:l                    // get max length
  ),
  h=[],
  a=a.map((n,i)=>
    [..."0".repeat(m-l[i])+n]    // add leading 0s to make all same length
    .map((d,j)=>d<h[j]?d:h[j]=d) // set each digit of h to max
  ),

  h.map((n,i)=>{
    i?o+=s+`
`:0;
    for(j=n;j--;o+=`
`)
      a.map(d=>
        o+=
          "|.:8"[
            d[i]-j<1?0
            :i<m-1?1
            :d[i]-1?2:
            3
          ]
      )
  }),
  o
)

Przykład

Dane wejściowe: tablica liczb: Dane [4,8,15,16,23,42]
wyjściowe:

|||||.
|||||.
||||..
||....
||||||
|:||||
|:||||
|:|:||
|:::||
::::||
:::::|
::::::
::::::
Aᴄʜᴇʀᴏɴғᴀɪʟ
źródło
+1 imponująca gra w golfa. Czy podasz przykład z danymi wejściowymi i wyjściowymi?
DavidC
@DavidC Dzięki! I przykład jest zawarty. Wywołaj go z konsoli i zwróci ciąg. :)
Aᴄʜᴇʀᴏɴғᴀɪʟ
7

Python 3, 624 598 595 574 561 535 532 527 525 426 345 328 324 294 288 286 283 280 267 265 255 251 245 238 235 234 230 228 bajtów

z=input().split();v=max(map(len,z));d=''.join(i.zfill(v)for i in z);x=['']*len(z)
for k,c in enumerate(d):j=k%v;m=int(max(d[j::v]));c=int(c);x[k//v]+="|"*(m-c+0**m+(j>0))+":8."[(c<2)|-(j<v-1)]*c
for r in zip(*x):print(*r,sep='')

Cóż, skoro to pytanie wymagało odpowiedzi, podałem tutaj jedną, w której wejściem powinien być ciąg liczb oddzielony spacjami, np "204 1". Chłopcze, czy to długi. Wszelkie sugestie dotyczące gry w golfa (lub lepsze odpowiedzi) są mile widziane.

Edycja: bajty zapisane przez mieszanie tabulatorów i spacji.

Edycja: Zapisałem wiele bajtów, zmieniając sposób, w jaki otrzymałem cyfry liczby (utwórz listę z zerowanego łańcucha liczby, a następnie w treści kodu, transponuj, aby uzyskać setki cyfr, dziesięć cyfr itp. .)

Edycja: I zaoszczędziłem trochę, włączając ostatnią :8pętlę do głównej pętli quipu. Teraz gdybym tylko mógł dowiedzieć się, dlaczego b=d[j*v+i]==m(d[i::v])nie zadziała. Zrozumiałem, a rozwiązanie zajmuje zbyt wiele bajtów. (Liczba bajtów również spadła, ponieważ karty w jakiś sposób zmieniły się w cztery spacje. Prawdopodobnie było to formatowanie bloku kodu na tej stronie)

Edycja: Zreorganizowałem sposób tworzenia quipusu. Teraz tworzy jedno pasmo na raz, a następnie transponuje do drukowania.

Edycja: Zamieniłem moją odpowiedź z powrotem w program Python 3, aby zaoszczędzić trochę więcej bajtów.

Edycja: Znalazłem błąd w moim kodzie, który spowodował, że nie wyświetlał poprawnie zer na środku liczb (patrz przypadek testowy 204 1powyżej). Naprawiając to, udało mi się zagrać w golfa :)

Edycja: Zmieniłem drukowanie, aby zapisać 10 bajtów. I odłożyłem wszystkie stare liczby bajtów z powrotem, tylko dlatego.

Edycja: Gra w golfa przy vużyciu mapczterech bajtów. Podziękowania dla CarpetPython , ponieważ wpadłem na pomysł z ich odpowiedzi tutaj .

Edycja: zamieniłem środkową „pętlę for wewnątrz pętli for” w tylko jedną pętlę for na sześć bajtów.

Edycja: teraz używa enumerate. Już nie używa l=len(z). Zamieniono trójskładnik if-elsew trójskładnik listy. Zobacz szczegóły poniżej.

Edycja: Sp3000 zasugerował edycję printi warunek trójskładnikowy, które zapisały każdy bajt.

Nie golfowany:

s = input()
z = s.split()
v = max(map(len, z))                # the amount of digits of the largest number
d = ''.join(i.zfill(v) for i in z)  # pad zeroes until every number is the same length
                                     # then join the numbers into one string
x = ['']*len(z)                     # a list of strings for the output, one for each number

for k,c in enumerate(d):          # for every digit in every number
    i,j = divmod(k, v)            # i is the index of the number we're on
                                   # j is the index of the digit of the number we're on
    m = int(max(d[j::v]))         # the largest of all the digits in the j-th place
    c = int(c)                    # the digit in j-th place of the i-th number
    x[i] += "|"*(m-c+0**m+(j>0))  # pad | to size m-c, until the knots are correctly spaced
                                  # add a | if m<1, all j-th place digits are 0
                                  # add a | if j>0, if it's not at the start, as delimiters
    x[i] += ":8."[(c<2)|-(j<v-1)] * c
    # this is essentially the following code
    # if j<v-1:
    #     x[i] += "."*c      # . knots if not in the units place
    # else:
    #     if c == 1:
    #         x[i] += "8"*c  # 8 knots for ones in the units place
    #     else:
    #         x[i] += ":"*c  # : knots for something else is in the units place

for r in zip(*x):       # transpose so all the rows (the quipu strings) now hang down
    print(*r, sep='')    # join the strings together at each knot
                         # and print each on a separate line
Sherlock9
źródło
Czy jest tu coś specyficznego dla Pythona 3 ? Jeśli nie, konwersja do Pythona 2 może zaoszczędzić sporo bajtów
Cyoce
@Cyoce Nic nie jest specyficzne dla Python 3. Właśnie zacząłem w Pythonie 3, ponieważ mam taką wersję. Przetestuję wersję Python 2 na ideone lub coś takiego.
Sherlock9,
@Maltysen To nie działa z danymi wejściowymi zaczynającymi się od 0, takimi jak 0 12 4.
Sherlock9,
Możesz zapisać niektóre bajty, zmieniając tabulacje i spacje dla wcięć w Pythonie 2. Uważam, że 1 znak tabulacji == 8 spacji zgodnie z parserem wcięć Pythona
Cyoce
for r in zip(*x):print(''.join(r))->print(''.join(r)for r in zip(*x))
Leaky Nun
4

C, 238 235 bajtów

Polegaj na preprocesorze C, aby kod był jak najkrótszy. Jako efekt uboczny powoduje również, że jest prawie nieczytelny.

#define l strlen(a[i])
#define d l<k||a[i][l-k]-48
#define m(e) for(i=1;a[i];e<=r?i++:r++);
#define p(e) {m(!putchar(e?'|':k>1?46:d<2?56:58))puts("");}
k,r;main(int i,char**a){m(l)for(k=r,r=1;k;r=k>1){m(d)for(;r;r--)p(d<r)if(--k)p(1)}}

W Ubuntu 14.04 możesz skompilować kod w prosty sposób gcc quipu.c(zignoruj ​​ostrzeżenia). Przykład uruchamiania pliku wykonywalnego:

$ ./a.out 1 2 3 2 1
||:||
|:::|
8:::8

Testowane na wszystkich przypadkach testowych OP.

Nieskluczony kod źródłowy:

// Standard library; leaving out the includes still gives executable code despite the warnings.
#include <stdio.h>
#include <string.h>

// 4 preprocessor macros.
// Note: some of these actually make use of the fact that parentheses have been left out

// l: length of argument i
#define l     strlen(a[i])

// d: shorthand for a digit
#define d     l<k || a[i][l-k]-'0'

// m: loop across all arguments; calculates r as the maximum of expression e
#define m(e)  for (i=1; a[i]; e<=r ? i++ : r++);

// p: prints one line of output
// note: intentionally does not use the r++ code branch of m;
//       putchar always returns a non-zero number here, so !putchar is zero,
//       which is always <=r (because r is never negative)
// note: the semicolon after m(...) is redundant;
//       the definition of m already contains a semicolon
// note: puts("") outputs a newline
#define p(e)  { m(!putchar(e ? '|' : k > 1 ? '.' : d < 2 ? '8' : ':')); puts(""); }

// k: knot position; 1 for units, 2 for tens, 3 for hundreds...
int k;

// r: input and output value for m
// note: the first time we call m, we need r to be zero;
//       by defining it outside main, it is automatically initialized as such
int r;

// function main
// note: parameter i (normally named argc by convention) is not needed
//       (the last element of argv is known; it is followed by a NULL pointer)
//       but we cannot leave it out (otherwise we cannot access argv)
//       so it serves as a local variable (to loop through arguments; see m)
// note: parameter a (normally named argv by convention)
//       is the array of arguments (starting from index 1)
int main(int i, char **a)
{
    // Determine the longest argument; store its length in r.
    // This is the number of knot positions to consider.
    m(l)

    // Iterate k through the knot positions from top to bottom.
    // Note: k > 0 has been abbreviated to k.
    // Note: for each iteration, we also initialize r with either 0 or 1.
    //       0 = suppress printing when all knots are zero
    //       1 = always print, even when all knots are zero
    for (k = r, r = 1; k > 0; r = k > 1)
    {
        // Determine the highest digit at this knot position.
        // Note: due to the absence of parentheses, d mixes up with <=r into:
        // (l < k) || (a[i][l-k]-'0' <= r)
        m(d)

        // Count the digits down.
        for (; r; r--)
        {
            // Print a single line of output.
            // When d (the digit in the current strand) is less than the counter,
            // then print a '|', otherwise print a knot.
            p(d < r)
        }

        // Decrement k (go to next knot position).
        // If this was not the last iteration...
        if (--k > 0)
        {
            // Print separator line.
            p(1)
        }
    }

    // Return exit code zero; redundant.
    return 0;
}
Ruud Helderman
źródło
Gratulacje! Jako najkrótsza odpowiedź opublikowana w okresie nagrody, otrzymałeś moją nagrodę w wysokości +50 powtórzeń. Niezła odpowiedź! :)
Alex A.
4

Mathematica 436 453 357 352 347 bajtów

t=Transpose;y=ConstantArray;a=Table;
g@j_:=(s=t[PadLeft[#,Max[Length/@i]]&/@(i=IntegerDigits@#)]&;p_~u~o_:=(m=Max@p;c=If[o==-2,":","."];w=If[o==-2,"8","."];p//.{0->a["|",Max@{1,m}],1->Join[a["|",{m-1}],{w}],n_/;MemberQ[2~Range~9,n]:>Join[y["|",m-n ],c~y~n]});t[Join@@@t@Join[u[#,0]&/@Most@#,u[#,-2]&/@{#[[-1]]}]]&[Riffle[(s@j),{a[0,Length@j]}]]//Grid)

Powyższe

  • Dzieli każdą liczbę całkowitą na listę cyfr, używając IntegerDigits; wstawia każdą liczbę zerami po lewej stronie (aby zapewnić równe odstępy); każdy numer wejściowy, teraz rozłożony na cyfry, odpowiada rzędowi tablicy; każda kolumna reprezentuje wartość miejsca. Tablica jest transponowana.
  • Zastępuje cyfry listą węzłów dopełnieniem. Dla jednostek zastosowano nieco inną procedurę dopasowywania wzorców.

Przykład

g[Range[0, 50]]

pięćdziesiąt

DavidC
źródło
Transpose@Join? To powinno być, prawda?
CalculatorFeline
Tak. Dzięki za złapanie tego.
DavidC
Przestrzeń tuż przed tym.
CalculatorFeline
1

R - 446 444

Widzę, że nie ma jeszcze rozwiązania R, więc oto jedno. Funkcja przyjmuje wektor z liczbami całkowitymi.

function(x){r=nchar(max(x));c=length(x);m=matrix(0,r,c);for(i in 1:c){t=as.numeric(strsplit(as.character(x[i]),"")[[1]]);m[(r+1-length(t)):r,i]=t};Q=c();for(i in 1:r){d=m[i,];z=ifelse(max(d)>0,max(d),1);q=matrix("|",z,c);for(j in 1:c){v=m[i,j];if(i==r){if(v==1)q[z,j]=8;if(v>1)q[(z-v+1):z,j]=rep(":",v)};if(i<r){if(v>0)q[(z-v+1):z,j]=rep(".",v)}};if(i!=1&sum(d)>0)q=rbind(rep("|",c),q);Q=rbind(Q,q)};for(i in 1:nrow(Q))cat(Q[i,],sep="",fill=T)}

Bez golfa

# Some test data
test <- c(201, 0, 100, 222, 53)

# Define function
quipu <- function (x) {

    # Create matrix with a row for each digit and a column for each number
    r=nchar(max(x));c=length(x);m <- matrix(0,r,c)
    for(i in 1:c) {
        t=as.numeric(strsplit(as.character(x[i]),"")[[1]])
        m[(r+1-length(t)):r,i]=t
    }

    # Loop through each row (digit) starting at the top of the quipu
    Q=c() # Empty matrix to store quipu 
    for(i in 1:r){

        d=m[i,]
        z=ifelse(max(d)>0,max(d),1)
        q=matrix("|",z,c)

        # Loop through each column (number in the vector) starting at the leftmost quipu
        for(j in 1:c){

            # The digit
            v=m[i,j]

            # If it is the last segment of the quipu
            if(i==r){
                if(v==1){q[z,j]=8} # If unit digit =1
                if(v>1){q[(z-v+1):z,j]=rep(":",v)} # If unit digit >1               
            }

            # If it is not the last segment of the quipu
            if(i<r){
                if(v>0){q[(z-v+1):z,j]=rep(".",v)} # If non-unit digit >0   
            }
        }

        # Add segment to Q
        if(i!=1 & sum(d)>0){q=rbind(rep("|",c),q)}
        Q=rbind(Q,q)    
    }

    # Print quipu
    for(i in 1:nrow(Q)) {cat(Q[i,], sep="", fill=T)}
}

# Test
quipu(test)
Wolne loris
źródło
Czy trzeba if(v>0)w if(i<r)klauzuli? Czy R akceptuje zakres jak z+1:zwtedy v==0? Jeśli tak q[z+1:z,j]nie będzie to miało wpływu w ogóle, to myślę. Ponadto, czy R ma elsesłowo kluczowe i jakieś else ifsłowo kluczowe? Jeśli tak, będziesz mógł zagrać w golfa w niektórych z tych warunków.
Sherlock9
if(v>0)jest potrzebne, ponieważ jeśli v=0indeks będzie poza zakresem (tzn. będzie próbował uzyskać wiersz nrow + 1). R ma else, i faktycznie wypróbowałem twoją sugestię i wykorzystałem elsetam, gdzie to możliwe, ale okazała się to ta sama liczba bajtów.
Wolne loris