Oficjalny inspektor Ruby

30

Oto prosty rubin artystyczny ASCII :

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_\/

Jako jubiler dla ASCII Gemstone Corporation, Twoim zadaniem jest sprawdzenie nowo nabytych rubinów i pozostawienie notatki o wszelkich znalezionych wadach.

Na szczęście możliwe jest tylko 12 rodzajów wad, a twój dostawca gwarantuje, że żaden rubin nie będzie miał więcej niż jednej wady.

W 12 wady odpowiada zastąpieniu jednego z 12 wewnętrzną _, /lub \znaków rubinu z spacji ( ). Zewnętrzny obwód rubinu nigdy nie ma wad.

Wady są ponumerowane, zgodnie z którymi wewnętrzny charakter ma w miejscu miejsce:

numery wad

Rubin z wadą 1 wygląda następująco:

  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/

Rubin z wadą 11 wygląda następująco:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/

To ten sam pomysł dla wszystkich innych wad.

Wyzwanie

Napisz program lub funkcję, która pobiera ciąg jednego, potencjalnie wadliwego rubinu. Numer wady należy wydrukować lub zwrócić. Numer wady wynosi 0, jeśli nie ma wady.

Weź dane wejściowe z pliku tekstowego, standardowego wejścia lub argumentu funkcji łańcuchowej. Zwróć numer usterki lub wydrukuj go na standardowe wyjście.

Możesz założyć, że rubin ma końcową nową linię. Być może nie przyjąć, że ma jakieś wiodące spacje lub znaki nowej linii.

Najkrótszy kod w bajtach wygrywa. ( Poręczny licznik bajtów. )

Przypadki testowe

13 dokładnych rodzajów rubinów, a następnie bezpośrednio oczekiwany wynik:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_\/
0
  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/
1
  ___
 /\ /\
/_/ \_\
\ \_/ /
 \/_\/
2
  ___
 /\_/\
/_  \_\
\ \_/ /
 \/_\/
3
  ___
 /\_/\
/_/ \_\
\  _/ /
 \/_\/
4
  ___
 /\_/\
/_/ \_\
\ \ / /
 \/_\/
5
  ___
 /\_/\
/_/ \_\
\ \_  /
 \/_\/
6
  ___
 /\_/\
/_/ \ \
\ \_/ /
 \/_\/
7
  ___
 /\_ \
/_/ \_\
\ \_/ /
 \/_\/
8
  ___
 / _/\
/_/ \_\
\ \_/ /
 \/_\/
9
  ___
 /\_/\
/ / \_\
\ \_/ /
 \/_\/
10
  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/
11
  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_ /
12
Hobby Calvina
źródło
Aby wyjaśnić, rubin nie może mieć żadnych spacji, prawda?
Optymalizator
@Optimizer Correct
Calvin's Hobbies
@ Calvin'sHobbies Czy możemy również założyć, że dane wejściowe nie mają końcowego nowego wiersza?
lub
@orlp Tak. To cały sens maja .
Calvin's Hobbies,
Rubiny są symetryczne. Czy więc błąd 7 nie powinien być na przykład taki sam jak błąd 10?
DavidC

Odpowiedzi:

13

CJam, 27 23 bajtów

F7EC5ZV4DI8G6]qBb67%J%#

Konwertuj bazę 11, weź mod 67, weź mod 19 wyniku, a następnie znajdź indeks tego, co masz w tablicy

[15, 7, 14, 12, 5, 3, 0, 4, 13, 18, 8, 16, 6]

Magia!

Wypróbuj online .

Sp3000
źródło
34

Ruby 2.0, 69 bajtów

#!ruby -Kn0rdigest
p'×ñF<ìX‚ɲŸ_'.index Digest::MD5.digest(gets)[0]

Hexdump (aby wiernie pokazać dane binarne w ciągu):

00000000  23 21 72 75 62 79 20 2d  4b 6e 30 72 64 69 67 65  |#!ruby -Kn0rdige|
00000010  73 74 0a 70 27 d7 f1 46  3c 1f ec 58 82 c9 b2 9f  |st.p'..F<..X....|
00000020  5f 02 27 2e 69 6e 64 65  78 20 44 69 67 65 73 74  |_.'.index Digest|
00000030  3a 3a 4d 44 35 2e 64 69  67 65 73 74 28 67 65 74  |::MD5.digest(get|
00000040  73 29 5b 30 5d                                    |s)[0]|

Wyjaśnienie:

  1. -KnOpcja odczytuje jako plik źródłowy ASCII-8BIT(binarne).
  2. -0Opcja pozwala getsczytać w całej wejście (i nie tylko jednej linii).
  3. -rdigestOpcja ładuje digestmoduł, który zapewnia Digest::MD5.
  4. Kod wykonuje następnie MD5 danych wejściowych, pobiera pierwszy bajt skrótu i ​​pobiera indeks w podanym ciągu binarnym.
Chris Jester-Young
źródło
Szczęście, że MD5 jest wyjątkowy pod względem samego pierwszego char
Optimizer
15
Nie jest wymagane szczęście. Każdy bajt ma 256 możliwości, więc pierwszy bajt różni się dla 13 skrótów nie jest niczym niezwykłym. Ale jeśli zderzyły się z jakiegokolwiek powodu, użyłbym drugiego bajtu skrótu.
Chris Jester-Young,
14
Napisz inspektora Ruby w Ruby. Naturalnie!
Maszt
Następne wyzwanie:
sprawdź
7

Julia, 90 59 bajtów

Zdecydowanie nie najkrótsza, ale piękna dziewica Julia z wielką starannością kontroluje królewskie rubiny.

s->search(s[vec([18 10 16 24 25 26 19 11 9 15 32 34])],' ')

Tworzy to funkcję lambda, która przyjmuje ciąg znaków si zwraca odpowiedni numer defektu ruby. Aby to nazwać, nadaj mu nazwę, np f=s->....

Niegolfowane + wyjaśnienie:

function f(s)
    # Strings can be indexed like arrays, so we can define d to
    # be a vector of indices corresponding to potential defect
    # locations

    d = vec([18 10 16 24 25 26 19 11 9 15 32 34])

    # Check the specified locations for defects, returning the
    # defect number as the index where a space was found and
    # was not expected. If no spaces are found, 0 is returned.

    search(s[d], ' ')
end

Przykłady:

julia> f("  ___
 /\\ /\\
/_/ \\_\\
\\ \\_/ \/
 \\/_\\/")
2

julia> f("  ___
 /\\_/\\
/_/ \\_\\
\\ \\_/ \/
 \\/_\\/")
0

Zauważ, że odwrotne ukośniki muszą być poprzedzone znakami ucieczki. Potwierdziłem w @ Calvin'sHobbies, że jest w porządku.

Daj mi znać, jeśli masz jakieś pytania lub sugestie!


Edycja: Zapisano 31 bajtów z pomocą Andrew Pilisera!

Alex A.
źródło
Możesz pozbyć się pętli for searchi indeksowania tablicy. s->(d=reshape([18 10 16 24 25 26 19 11 9 15 32 34],12);search(s[d],' ')). Nie podoba mi się przekształcanie, ale nie mogłem wymyślić krótszego sposobu na uzyskanie tablicy 1d.
Andrew mówi Przywróć Monikę
@AndrewPiliser: Dzięki, naprawdę doceniam twój wkład! Zredagowałem, aby użyć twojej sugestii. Także krótszy sposób niż reshape()do użycia vec(). :)
Alex A.,
7

> <> (Ryba) , 177 bajtów

To długie, ale wyjątkowe rozwiązanie. Program nie zawiera arytmetyki ani rozgałęzień oprócz wstawiania znaków wejściowych w ustalonych miejscach w kodzie.

Zauważ, że wszystkie sprawdzone znaki budujące ruby ​​( / \ _) mogą być „kopiami lustrzanymi” w kodzie> <>, które zmieniają kierunek wskaźnika instrukcji (IP).

Możemy użyć tych znaków wejściowych do zbudowania z nich labiryntu za pomocą instrukcji modyfikującej kod pi przy każdym wyjściu (utworzonym przez brakujące lustro na wejściu) możemy wydrukować odpowiednią liczbę.

iiiiiiiii19pi1cpi18piiii2bpi27pii28pi3apiiiii37pi49pi36piiiii00pi45pii46p

    ;
   ;n
  ;nb
 ;n6S    0n;
 n3SB   cn;
 8SB!  4n;
 SB!  1n;
>B! U9n;
 ! U5
  U7n
 Uan;
 2n;
 n;
 ;

Te S B Ulitery są te zmieniły się / \ _odpowiednio. Jeśli dane wejściowe są pełne ruby, końcowy kod staje się:

\iiiiiiii19pi1cpi18piiii2bpi27pii28pi3apiiiii37pi49pi36piiiii00pi45pii46p

    ;
   ;n
  ;nb
 ;n6/    0n;
 n3/\   cn;
 8/\!  4n;
 /\!  1n;
>\! _9n;
 ! _5
  _7n
 _an;
 2n;
 n;
 ;

Możesz wypróbować program dzięki temu świetnemu tłumaczowi wizualnemu online . Ponieważ nie możesz wprowadzać tam nowych wierszy, musisz zamiast tego użyć fikcyjnych znaków, aby wprowadzić pełny rubin, np SS___LS/\_/\L/_/S\_\L\S\_/S/LS\/_\/. (Spacje również zmieniły się na S z powodu przeceny).

randomra
źródło
5

CJam, 41 31 29 28 bajtów

"-RI)11a!"q103b1e3%A/c#

Jak zwykle, w przypadku znaków niedrukowalnych kliknij ten link .

Wypróbuj online tutaj

Wyjaśnienie wkrótce


Poprzednie podejście:

Całkiem pewne, że można to zmniejszyć, zmieniając logikę cyfr / konwersji. Ale tutaj jest pierwsza próba:

"<KJ[]\"O=":iqN-"/\\_ "4,er4b1e3%A/#

Jak zwykle, użyj tego linku do znaków niedrukowalnych.

Logika jest dość prosta

  • "Hash for each defect":i - To daje mi skrót za defekt jako indeks
  • qN-"/\\_ "4,er - zamienia znaki na liczby
  • 4b1e3%A/ - jest to unikalny numer w podstawowej liczbie przeliczonej
  • # Następnie po prostu znajduję indeks unikalnego numeru w haszu

Wypróbuj online tutaj

Optymalizator
źródło
Tak blisko, jestem o 1 postać niższa od ciebie!
lub
Och, mam już 28. Byłem zbyt zajęty, aby zaktualizować
Optymalizator
Myślę, że moja odpowiedź jest optymalna dla Pytha. Pyth naprawdę potrzebuje funkcji skrótu ( .hobecnie jest bezużyteczny, ponieważ wykorzystuje wbudowaną niewiarygodną i złą hash()), do tego czasu nie mogę zrobić nic lepszego.
lub
4

Poślizg , 123 108 + 3 = 111 bajtów

^6 (`\\`_.?<?.?[ _]?|`_(`\.?(<.?|>)|`/.?.?>.?.?).?)| `_(`\.?<.?>?.?.?|`/(.?>.?.?.?|<`_))| `/\`_.?(.<.?>?.?)?

Uruchom z flagami ni o, tj

py -3 slip.py regex.txt input.txt no

Możesz też spróbować online .


Slip jest językiem przypominającym wyrażenia regularne, który powstał w ramach wyzwania polegającego na dopasowaniu wzorca 2D . Poślizg może wykryć lokalizację wady za pomocą pflagi pozycji za pomocą następującego programu:

^6? `_[/\]|( `/|^6 `\)\`_

który szuka jednego z następujących wzorców (tutaj Soznacza to, że zaczyna się dopasowanie):

S_/    S_\    /_S    \_S    S/      _
                              _      \S

Wypróbuj online - współrzędne są wyprowadzane jako para (x, y). Wszystko brzmi jak normalne wyrażenie regularne, z wyjątkiem tego, że:

  • ` służy do ucieczki,
  • <> obróć wskaźnik dopasowania odpowiednio w lewo / w prawo,
  • ^6 ustawia wskaźnik dopasowania twarzą w lewo, a
  • \ przesuwa wskaźnik dopasowania prostopadle w prawo (np. jeśli wskaźnik jest skierowany w prawo, to idzie w dół o rząd)

Ale niestety potrzebujemy pojedynczej liczby od 0 do 12, która mówi, która wada została wykryta, a nie gdzie została wykryta. Slip ma tylko jedną metodę wyprowadzania pojedynczej liczby - nflagę, która wypisuje liczbę znalezionych dopasowań.

Aby to zrobić, rozszerzamy powyższe wyrażenie regularne, aby dopasować prawidłową liczbę razy dla każdej wady, za pomocą onakładającego się trybu dopasowania. Podział na elementy to:

1 11:    `_`\.?<.?>?.?.?
2 10:    `/\`_.?(.<.?>?.?)?
4 9:     `_`/(.?>.?.?.?|<`_)
3 12:   ^6 `_`/.?.?>.?.?.?
5 7:    ^6 `\\`_.?<?.?[ _]?
6 8:    ^6 `_`\.?(<.?|>).?

Tak, to nadmierne użycie, ?aby uzyskać prawidłowe liczby: P

Sp3000
źródło
Haha, niesamowite. Muszę dodać więcej rodzajów wyników do mojego języka.
BMac
4

JavaScript (ES6), 67 72

Po prostu szuka pustych miejsc w podanych 12 lokalizacjach

Edytuj Zapisane 5 bajtów, dzięki @apsillers

F=b=>[..."0h9fnopia8evx"].map((v,i)=>b[parseInt(v,34)]>' '?0:d=i)|d

Przetestuj w konsoli Firefox / FireBug

x='  ___\n /\\_/\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/' // no defects
;[...x].forEach((c,p,a)=>{
  a[p]=' ' // put a blank
  y=a.join('') // rebuild a string
  d=F(y) // check
  if (d) console.log('\n'+y+'\n'+d) // if defect, output
  a[p]=c // remove the blamk
})

Wydajność

  ___
 / _/\
/_/ \_\
\ \_/ /
 \/_\/
9

  ___
 /\ /\
/_/ \_\
\ \_/ /
 \/_\/
2

  ___
 /\_ \
/_/ \_\
\ \_/ /
 \/_\/
8

  ___
 /\_/\
/ / \_\
\ \_/ /
 \/_\/
10

  ___
 /\_/\
/_  \_\
\ \_/ /
 \/_\/
3

  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/
1

  ___
 /\_/\
/_/ \ \
\ \_/ /
 \/_\/
7

  ___
 /\_/\
/_/ \_\
\  _/ /
 \/_\/
4

  ___
 /\_/\
/_/ \_\
\ \ / /
 \/_\/
5

  ___
 /\_/\
/_/ \_\
\ \_  /
 \/_\/
6

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/
11

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_ /
12
edc65
źródło
@apsillers to dobrze, a nawet lepiej, dzięki. Ponieważ ciąg wejściowy zawsze zaczyna się od „”, wiodące 0 wymusza inicjalizację d do i w pierwszej pętli, więc „d = 0” można usunąć.
edc65
2

C, 98 84 bajtów

g(char*b){char*c="/'-5670(&,=?",*a=c;for(;*c&&!(*b=b[*c++-30]-32?0:c-a););return*b;}

AKTUALIZACJA: Trochę bardziej sprytna w odniesieniu do łańcucha i naprawiono problem z nieuszkodzonymi rubinami.

Rozpruty:

g(char*b){
    char*c="/'-5670(&,=?",*a=c;
    for(;*c&&!(*b=b[*c++-30]-32?0:c-a);)
        ;
    return*b;
}

Całkiem proste i prawie 100 bajtów.

Dla testów:

#include "stdio.h"
int main() {
    char b[100];
    scanf("%35c", b);
    printf("%d\n", g(b));
    return 0;
}

Wejście do STDIN.

Jak to działa

Każda wada rubinu ma inną postać. Ta lista pokazuje, gdzie występuje każda wada w ciągu wejściowym:

Defect 1: 17
Defect 2: 9
Defect 3: 15
Defect 4: 23
Defect 5: 24
Defect 6: 25
Defect 7: 18
Defect 8: 10
Defect 9: 8
Defect 10: 14
Defect 11: 31
Defect 12: 33

Ponieważ tworzenie tablicy {17,9,15,23,24,25,18,10,8,14,31,33}kosztuje dużo bajtów, znajdujemy krótszy sposób na utworzenie tej listy. Zauważ, że dodanie 30 do każdej liczby daje listę liczb całkowitych, które mogą być reprezentowane jako drukowalne znaki ASCII. Ta lista jest następująca: "/'-5670(&,=?". Zatem możemy ustawić tablicę znaków (w kodzie c) na ten ciąg i po prostu odjąć 30 od każdej wartości, którą pobieramy z tej listy, aby uzyskać naszą oryginalną tablicę liczb całkowitych. Określamy, aaby być równym w ccelu śledzenia, jak daleko doszliśmy na liście. W kodzie pozostaje tylko forpętla. Sprawdza, aby upewnić się, że jeszcze nie dotarliśmy do końca c, a następnie sprawdza, czy znakiem bbieżącego cjest spacja (ASCII 32). Jeśli tak, ustawiamy pierwszy, nieużywany elementb na numer wady i zwróć go.

BrainSteel
źródło
2

Python 2, 146 88 86 71 bajtów

Funkcja fsprawdza lokalizację każdego segmentu i zwraca indeks segmentu defektu. Test pierwszego bajtu w ciągu wejściowym gwarantuje, że wrócimy, 0jeśli nie zostaną znalezione żadne defekty.

Teraz pakujemy przesunięcia segmentów w zwarty ciąg i używamy ord()do ich odzyskania:

f=lambda s:sum(n*(s[ord('ARJPXYZSKIO`b'[n])-65]<'!')for n in range(13))

Testowanie z doskonałym rubinem:

f('  ___\n /\\_/\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/')
0

Testowanie z segmentem 2 zastąpionym spacją:

f('  ___\n /\\ /\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/')
2

EDYCJA: Dzięki @xnor za dobrą sum(n*bool for n in...)technikę.

EDIT2: Podziękowania dla @ Sp3000 za dodatkowe wskazówki dotyczące gry w golfa.

Logic Knight
źródło
2
Myślę, że możesz zapisywać znaki używając sumy wskaźników sum(n*(s[...]==' ')for ...).
xnor
1
Biorąc pod uwagę, że znaki są wymieniane po przestrzeni, prawdopodobnie można zrobić coś takiego <'!'zamiast ==' 'na bajt. Możesz również wygenerować listę za pomocą map(ord, ...), ale nie jestem pewien, co sądzisz o materiałach do
drukowania
1

Pyth, 35 31 28 bajtów

hx"*6#,54@"C%imCds.zT67

Wymaga załatanego Pytha , obecna najnowsza wersja Pyth'a zawiera błąd, .zktóry usuwa końcowe znaki.

Ta wersja nie używa funkcji skrótu, nadużywa podstawowej funkcji konwersji w języku Pyth, aby obliczyć bardzo głupi, ale działający skrót. Następnie przekształcamy ten skrót na znak i sprawdzamy jego indeks w postaci ciągu.

Odpowiedź zawiera znaki niedrukowalne, użyj tego kodu Python3, aby dokładnie wygenerować program na komputerze:

garbage = [42, 22, 54, 35, 44, 28, 31, 53, 52, 64, 16, 11]
prg = 'hx"' + "".join(chr(c) for c in garbage) +'"C%imCds.zT67'
open("golf_gen.pyth", "w").write(prg)
print(len(prg))
orlp
źródło
1

Haskell, 73 bajty

f l=last[x|x<-[0..12],l!!([0,17,9,15,23,24,25,18,10,8,14,31,33]!!x)==' ']

Ta sama strategia, co wiele innych rozwiązań: szukanie przestrzeni w danych lokalizacjach. Wyszukiwanie zwraca listę indeksów, z których pobieram ostatni element, ponieważ zawsze istnieje trafienie dla indeksu 0.

nimi
źródło
0

05AB1E , 16 bajtów

•W)Ì3ô;4(•₆вèðk>

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

W3ô;4(•        # Push compressed integer 2272064612422082397
          ₆в      # Converted to Base-36 as list: [17,9,15,23,24,25,18,10,8,14,31,33]
            è     # Index each into the (implicit) input-string
             ðk   # Get the 0-based index of the first space in the indexed characters
                  # (-1 if not found, which means the ruby had no defects)
               >  # And increase it by 1 (which is output implicitly as result)

Zobacz moją wskazówkę 05AB1E (sekcje Jak kompresować duże liczby całkowite? I Jak kompresować listy liczb całkowitych? ), Aby zrozumieć, dlaczego •W)Ì3ô;4(•jest 2272064612422082397i •W)Ì3ô;4(•₆вjest [17,9,15,23,24,25,18,10,8,14,31,33].

Kevin Cruijssen
źródło