Kiedy Mikołaj wchodzi do piwnicy? (AOC dzień 1)

20

Powielam drugą część pierwszego dnia Adwentu Kodeksu, za zgodą twórcy.

Święty Mikołaj próbuje dostarczyć prezenty w dużym budynku mieszkalnym, ale nie może znaleźć właściwej podłogi - wskazówki, które otrzymał, są nieco mylące. Zaczyna na parterze (piętro 0), a następnie postępuje zgodnie z instrukcjami jedna postać na raz.

Nawias otwierający (oznacza, że ​​powinien wejść na jedno piętro, i nawias zamykający ), oznacza, że ​​powinien zejść o jedno piętro.

Budynek mieszkalny jest bardzo wysoki, a piwnica bardzo głęboka; nigdy nie znajdzie górnej ani dolnej podłogi.

Biorąc pod uwagę zestaw instrukcji, znajdź pozycję pierwszego znaku, który powoduje, że wchodzi on do piwnicy (piętro -1).

Jako przykłady:

wejście )powoduje, że wchodzi on do piwnicy na pozycji postaci 1.

wejście ()())powoduje, że wchodzi on do piwnicy na pozycji postaci 5.

Podano tutaj długi wkład , który powinien dać rozwiązanie 1797.

To jest golf golfowy, więc wygrywa najkrótsze rozwiązanie!

Simmons
źródło
Czy musimy używać tych dokładnych znaków?
Niebieski
1
@muddyfish W oryginalnych wyzwaniach dane wejściowe były podawane w określonej formie i tak często kluczową częścią wyzwania było analizowanie danych wejściowych; podczas gdy nie chcę, aby stało się to „problemem kameleona”, myślę, że duchem oryginału jest to, że dane wejściowe powinny być ciągiem nawiasów. Zdaję sobie sprawę, że to uprzywilejowuje niektóre języki w stosunku do innych, ale wzywam wyborców do wzięcia tego pod uwagę przy przyznawaniu głosów za rozwiązaniami.
A Simmons,
Bardzo ściśle związany z liczbami binarnymi podlegającymi zmianie przez rodziców ... Nie czuję się wystarczająco silnie, aby to był dupek, więc po prostu zostawię komentarz.
AdmBorkBork
@ TimmyD Rozumiem, co masz na myśli, ale wydaje mi się, że to pytanie jest na tyle inne, że konkurencyjne odpowiedzi nie będą w stanie wyciągnąć zbyt wiele z tego pytania!
A Simmons,
1
Próbuję rozwiązać to w SMBF (w zasadzie BF), a ten język SUCKS debugować ... ugh.
mbomb007

Odpowiedzi:

17

Galaretka, 8 7 bajtów

O-*+\i-

Dzięki @ Sp3000 za grę w golfa przy 1 bajcie!

Wypróbuj online!

Jak to działa

O-*+\i-    Main link. Input: s (string)

O          Ordinal; replace each character with its code point.
           This maps "()" to [48, 49].
 -*        Apply x -> (-1) ** x.
           This maps [48, 49] to [1, -1].
   +\      Compute the cumulative sum, i.e., the list of partial sums.
     i-    Find the first index of -1.
Dennis
źródło
16

Python 2, 44 bajty

try:input()
except Exception,e:print e[1][2]

To sprytne rozwiązanie zostało znalezione przez hallvabo, xsot, mitchs i whatisgolf w sprawie tego problemu na Anarchy Golf . Jeśli ktoś z was zechce go zamiast tego opublikować, usunę to.

Sztuką jest pozwolić parserowi Pythona na wykonanie pracy. Funkcja input()próbuje oszacować ciąg wejściowy i zgłasza błąd przy pierwszym niedopasowanym paren. Ten błąd, gdy zostanie złapany, ma formę

SyntaxError('unexpected EOF while parsing', ('<string>', 1, 1, ')'))

który zawiera numer znaku, w którym wystąpił błąd.

xnor
źródło
7

Python, 79 77 bajtów

lambda m:[sum([2*(z<')')-1for z in m][:g])for g in range(len(m)+1)].index(-1)

Prawdopodobnie jest na to lepszy sposób, ale nie mam pomysłów. To także mój pierwszy post na codegolf.

Dzięki @Erwan. do gry w golfa poza 2 bajtami.

drobilc
źródło
Witamy na stronie! To jest bardzo fajny pierwszy post. :)
Alex A.
można zastąpić [0:g]przez[:g]
Erwan
i ta wymiana oszczędzania 1 bajtów myślę -2*ord(z)+81o2*(z<')')-1
Erwan
5

Python 3, 59

Zaoszczędzono 3 bajty dzięki grc.

Naprawdę nie lubię ręcznego indeksowania ciągów w Pythonie. Czuje się tak źle.

def f(x):
 c=q=0
 while-~c:c+=1-(x[q]>'(')*2;q+=1
 return q
Morgan Thrapp
źródło
5

C, 55 bajtów

g;main(f){for(;f;g++)f+=81-getchar()*2;printf("%d",g);}

Wypróbuj tutaj .

Edycja: Nie jestem pewien, dlaczego zostawiłem tam nieużywaną zmienną ...

Cole Cameron
źródło
5

CJam, 10 bajtów

0l'_*:~1#)

lub

0l'_*~]1#)

lub (kredyty dla Dennisa)

Wl+'_*:~1#

Sprawdź to tutaj.

Wyjaśnienie

Jak już zauważył A Simmons, ()jest to szczęśliwy wybór dla CJam, ponieważ są to odpowiednio operatory zmniejszania / zwiększania. Oznacza to, że jeśli zaczynamy od zera, szukamy kroku, w którym Święty Mikołaj osiągnie piętro 1.

0   e# Push 0, the initial floor.
l   e# Read input.
'_* e# Riffle the input string with underscores, which duplicate the top of the stack.
:~  e# Evaluate each character, using a map which wraps the result in an array.
1#  e# Find the position of the first 1.
)   e# Increment because we're looking for a one-based index.
Martin Ender
źródło
4

Labirynt , 18 bajtów

+(+"#(!@
:  :
%2_,

Wypróbuj online! Ta odpowiedź była wynikiem współpracy z @ MartinBüttner.

Wyjaśnienie

Zwykły podkład do labiryntu (mówię „zwykły”, ale tak naprawdę przepisuję to za każdym razem):

  • Labirynt to język 2D oparty na stosie, którego wykonywanie rozpoczyna się od pierwszego prawidłowego znaku (tutaj u góry po lewej). Na każdym skrzyżowaniu, gdzie istnieją dwie lub więcej możliwych ścieżek dla wskaźnika instrukcji do sprawdzenia, góra stosu jest sprawdzana, aby określić, gdzie iść dalej. Negatyw to skręt w lewo, zero to przejście do przodu, a dodatnie to skręt w prawo.
  • Stos jest bezdenny i wypełniony zerami, więc wyskakiwanie z pustego stosu nie jest błędem.
  • Cyfry w kodzie źródłowym nie wypychają odpowiedniej liczby - zamiast tego wyskakują na górze stosu i pchają n*10 + <digit>. Pozwala to na łatwe budowanie dużych liczb. Aby rozpocząć nowy numer, użyj _, który wypycha zero.

Ten kod jest nieco dziwny, ponieważ do celów golfowych główna pętla łączy dwa zadania w jedno. W pierwszej połowie pierwszego przejścia oto, co się dzieje:

+(+             Add two zeroes, decrement, add with zero
                This leaves -1 on the stack
"               NOP at a junction. -1 is negative so we try to turn left, fail, and
                turn right instead.
:               Duplicate -1

Teraz, gdy stos został zainicjowany z -1 na górze, można rozpocząć przetwarzanie. Oto, co robi główna pętla.

,               Read a byte of input
_2%             Take modulo 2.
:+              Duplicate and add, i.e. double
(               Decrement
                This maps "(" -> -1, ")" -> 1
+               Add to running total
"               NOP at a junction. Go forward if zero, otherwise turn right.
:               Duplicate the top of the stack

Ostatni duplikat dodaje element do stosu dla każdej wykonywanej iteracji. Jest to ważne, ponieważ kiedy osiągamy zero i idziemy do przodu w NOP, robimy:

#               Push stack depth
(               Decrement
!               Output as num
@               Terminate
Sp3000
źródło
3

Oracle SQL 11.2, 160 159 bajtów

SELECT MIN(l)FROM(SELECT l,SUM(m)OVER(ORDER BY l)p FROM(SELECT LEVEL l,DECODE(SUBSTR(:1,LEVEL,1),'(',1,-1)m FROM DUAL CONNECT BY LEVEL<=LENGTH(:1)))WHERE p=-1;

Nie grał w golfa

SELECT MIN(l) -- Keep the min level
FROM(
  SELECT l,SUM(m)OVER(ORDER BY l)p -- Sum the () up to the current row
  FROM(
    SELECT LEVEL l,DECODE(SUBSTR(:1,LEVEL,1),'(',1,-1)m -- ( equal 1 and ) equal -1 
    FROM DUAL 
    CONNECT BY LEVEL<= LENGTH(:1)
  )
)
WHERE p=-1 -- Keep the rows where the () sum is equal to -1
Jeto
źródło
3

Siatkówka ,22 21

! M` ^ ((\ () | (? <-2>.)) +

Wypróbuj online lub wypróbuj duży przypadek testowy. (Adres URL jest duży dla dużego przypadku testowego, daj mi znać, jeśli się zepsuje, wydaje się OK w chrome).

1 bajt zapisany dzięki Martinowi!

Dopasowujemy pierwszy zestaw zrównoważonych nawiasów i wyodrębniamy go, a następnie zliczamy liczbę przypadków, gdy pusty ciąg dopasuje ten wynik. Nie jestem pewien, czy jest to najładniejszy sposób na to w Retinie, szczególnie jeśli tryb PCRE sprawia, że ​​jest on krótszy, ale korzystanie z $#_zastępowania wydawało się dłuższe z powodu jednego błędu i problemu z więcej niż jednym dopasowaniem.

Algorytm ten powoduje dziwne zachowanie w przypadku nieprawidłowych danych wejściowych, zasadniczo zakłada, że ​​jeśli Mikołaj nie dotrze do piwnicy, w tajemniczy sposób teleportuje się tam po innych ruchach.

FryAmTheEggman
źródło
3

Grep + AWK, 51 bajtów

grep -o .|awk '/\(/{s++}/)/{s--}s<0{print NR;exit}'

grepKomenda umieszcza na każdy znak nowej linii.

Robert Benson
źródło
3

Pyth, 13 bajtów

f!hsm^_1Cd<zT

Wyjaśnienie

              - autoassign z = input()
f             - First where V returns Truthy.
          <zT -     z[:T]
    m         -    [V for d in ^]
        Cd    -     ord(d)
     ^_1      -      -1**^
   s          -   sum(^)
 !h           -  not (^+1)

Wypróbuj tutaj

Stary algorytm, 15 bajtów

f!h-/J<zT\(/J\)

Wyjaśnienie:

                - autoassign z = input()
f               - First where V returns Truthy.
      <zT       -      z[:T]
     J          -     autoassign J = ^
    /    \(     -    ^.count("(")
           /J\) -    J.count(")")
   -            -   ^-^
 !h             -  not (^+1)

Wypróbuj tutaj

Lub jeśli wolno używać znaków innych niż (i ), 9 bajtów (przenoszenie przetwarzania wstępnego na dane wejściowe)

f!.v+<zT1

Wyjaśnienie

          - autoassign z = input()
f         - First where V returns Truthy.
     <zT  -     z[:T]
    +   1 -    ^+"1"
  .v      -   eval(^)
 !        -  not ^

Wypróbuj tutaj

niebieski
źródło
3

JavaScript (ES6), 58 bajtów

f=(s,t=s)=>s<')'?f(s.replace('()',''),t):t.length-s.length+1

Działa poprzez rekurencyjne usuwanie pary pasujących ()s, aż pierwszy znak to ). Ostrzeżenie: nie próbuj tego na ciągach, które nie mają wystarczającej liczby )s. Przykład:

((()())()))
((())()))
(()()))
(()))
())
)

W tym momencie widzi, że w sumie usunięto 12 znaków, więc odpowiedź to 13.

Neil
źródło
Zamiast tego możesz umieścić ten komentarz w swojej odpowiedzi.
mbomb007
3

MATL , 12 11 bajtów

1 bajt zapisany przy użyciu pomysłu Dennisa obliczenia -1 podniesionego do ciągu wejściowego

1_j^Ys0<f1)

Wypróbuj online!

1_         % number -1
j          % take string input
^          % element-wise power. This transforms '('  to 1 and ')' to -1
Ys         % cumulative sum
0<         % true for negative values
f          % find all such values 
1)         % pick first. Implicit display
Luis Mendo
źródło
2

CJam, 12 10 bajtów

0q{~_}%1#)

Wypróbuj tutaj.

Dwa bajty zapisane dzięki Martinowi.

Wyjaśnienie:

0              Load 0 onto the stack
 q             Load input onto the stack without evaluating
  {  }       Code block
   ~_          Evaluate the next command and duplicate the top stack element. The format of the question is good for CJam and Golfscript since ) and ( are increment and decrement operators (though the wrong way round).
        %      Map this code block over the string. This yields an array of Santa's floor positions
         1#   Find the first instance of a 1, since decrement and increment are swapped
           )  Fix the off-by-1 error caused by zero-indexing
Simmons
źródło
2

JavaScript, 117 bajtów

o=f=0;i=prompt().split('');for(c in i){switch (i[c]){case '(':f++;break;case ')':f--;if(f<0){alert(o+1);i=[];}}o++;}

Ignoruje inne postacie. Używa prompti alert.

Solomon Ucko
źródło
2

Perl, 34 + 1 = 35 bajtów

$.+=s+.+++s+\)++while")"gt$_;$_=$.

Dzięki Dennisowi za wskazówki.

Uruchom z -pflagą. Działa w Perlu 5.10, ale późniejsze wersje potrzebują tutaj miejsca:++ while

Starsza, nie golfowa wersja:

$_ = <>;                # get a line of input
while ($_ lt ')') {     # while it begins with a (
    s/.//;              # remove the first (
    s/\)//;             # remove the first )
    $i += 2;            # increase index by 2
}
print $i + 1;           # print the position
grc
źródło
2

Python, 44 bajty

f=lambda s,i=1:i and-~f(s[1:],i-1+2*(s<')'))

Piętro izaczyna się od, 1więc kończymy na iwartości falsey 0. Jeśli nie zostanie zakończone, rekurencyjnie dodaj jeden, aby uzyskać wynik po usunięciu pierwszego znaku i zaktualizowaniu numeru podłogi na podstawie tego znaku.

xnor
źródło
2

JavaScript, 57 bajtów

p=>{c=0;for(i in p){c+=p[i]==')'?-1:1;if(c<0)return+i+1}}

Całkiem proste, po prostu iteruje po danych wejściowych, incs if '(' decs if ')'. Zwraca pierwszy negatywny.

SethWhite
źródło
2

Ruby, 47 bajtów

Funkcja anonimowa.

->s{i,l=-1,0;l+=s[i+=1]>?(?-1:1 while l>-1;i+1}
Wartość tuszu
źródło
1

C, 73 bajty

main(f,c){f=c=0;for(;f!=-1;c++){f+=1-((getchar()&1)<<1);}printf("%d",c);}

Oczekuje danych wejściowych na STDIN; żadne znaki inne niż (i )mogą pojawiać się na wejściu (przynajmniej dopóki nie osiągniemy odpowiedzi). Dane wejściowe muszą być ASCII.

Emituje odpowiedź na STDOUT.

Używa 1-bitowej różnicy między ASCII dla (i ).

/* old-style arguments, implicitly int */
main(x, f)
{
    /* c is our character counter, f is the floor*/
    c = f = 0;
    /* increase c while f is not -1 */
    for (;f != -1; c++) {
        /* use difference in LSB to add one for (, subtract one for ) */
        f += 1-((getchar()&1)<<1);
    }
    /* answer */
    printf("%d", c);
}

Ładnie sformatowana wersja:

David Morris
źródło
Czy można przejść f=c=0do inicjalizacji pętli, for(f=c=0;f!=...aby zapisać bajt?
AdmBorkBork
@ TimmyD lepiej, aby były globalne, aby były automatycznie inicjowane.
Cole Cameron
1

PowerShell, 75 65 62 bajtów

[char[]]$args[0]|%{$c+=(1,-1)[$_%40];$d++;if($c-lt0){$d;exit}}

Wykorzystuje podobną techniką jak na Parenthifiable liczb binarnych pętli wszystkich znaków wejściowych, utrzymując prowadzenie $counter stanowi +1dla siebie (i -1dla siebie ), a następnie sprawdzić czy mamy uderzyć ujemny (czyli jesteśmy w piwnicy).

Edytuj - zapisano 10 bajtów przez iterację rzeczywistych znaków zamiast ich indeksów
Edytuj 2 - zapisano 3 dodatkowe bajty przez zamianę kontroli równości dla modulo, więc rzutowanie jest niejawne

AdmBorkBork
źródło
1

Mathematica, 62 55 bajtów

Position[Accumulate[(-1)^ToCharacterCode@#],-1][[1,1]]&

Wszystkie długie nazwy funkcji! Działa podobnie do odpowiedzi Simmonsa na CJam.

LegionMammal978
źródło
1

Befunge 25 bajtów

Wyjścia jednostkowe. To rozpocznie cię na pierwszym piętrze i potrwa do 0.

1<\1_v#:+-*2%2~
:#._@>$1>
MegaTom
źródło
1

Rakieta (102)

(λ(s)(let l((c 0)(b 0)(s(string->list s)))(if(> 0 b)c(l(+ 1 c)((if(eqv?(car s)#\()+ -)b 1)(cdr s)))))

Nie golfił

(λ (input)
  (let loop ((count 0) (balance 0) (chars (string->list input)))
    (if (> 0 balance)
        count
        (loop (+ 1 count)
              ((if (eqv? (car chars) #\() + -) balance 1)
              (cdr chars)))))
Sylwester
źródło
1

APL, 18 znaków

{1⍳⍨¯1=+\¯1*')'=⍵}

Po angielsku:

  • ¯1*')'=⍵: -1 gdzie input = ")", 1 w przeciwnym razie;
  • +\: suma bieżąca;
  • 1⍳⍨¯1=: znajdź indeks pierwszego -1.
lstefano
źródło
1

Lua, 92 89 87 bajtów

Przyjmuje argument wiersza poleceń.

Edycja: Zapisano 3 bajty

Edycja: Zapisano 2 bajty i poprawiono błąd, który mógł się zdarzyć w przypadkach na krawędziach, teraz wyświetla dane wyjściowe za pomocą kodu wyjścia

r=0i=0(...):gsub(".",function(c)i=i+1r=r+(c==")"and-1or 1)if r<0then os.exit(i)end end)

Nie golfił

r,i=0,0                     -- set r (the actual floor), and i(the character count)
(...):gsub(".",function(c) -- apply an anonymous functions on each character of the input
  i,r=i+1,                  -- increment i
      r+(c==")"and -1 or 1) -- decrement r if c==")", increment it otherwise
  if r<0 then os.exit(i)end -- if r==-1, exit and output the current index
end)
Katenkyo
źródło
1

k / kona , 23 21 bajtów

2 bajty zapisane przez usunięcie niepotrzebnych nawiasów.

{1+(+\1 -1"()"?x)?-1}

Stosowanie:

k){1+(+\1 -1"()"?x)?-1} "())"
3
Simon Major
źródło
0

Perl, 40 + 1 = 41 bajtów

$y++,($i+=/\(/*2-1)<0&&last for/./g;$_=$y

Wymaga -pflagi:

$ perl -pe'$y++,($i+=/\(/*2-1)<0&&last for/./g;$_=$y' <<< '()())'
5
$ perl -pe'$y++,($i+=/\(/*2-1)<0&&last for/./g;$_=$y' 1797.txt
1797

Zakłada prawidłowe dane wejściowe.

Jak to działa:

                                           # -p read line by line into $_ and auto prints at the end
        $y++,                              # Counter for steps taken
             ($i+=/\(/*2-1) < 0            # The match /\(/ will give 1 or 0 in a numeric context 1 for `(` and 0 for anything else
                                           # times it by 2 and subtracting -1 will yield 1 or -1
                               && last     # End the iteration if $i < 0
for/./g;                                   # Iterate over each items in the input
                                      $_=$y# Print the output
andlrc
źródło
0

JavaScript (ES6), 68 67 bajtów

(s,r,f=0)=>s.split``.map((l,i)=>(f+=l=='('?1:-1,f<0?r=r||++i:0))&&r

Pobiera dane wejściowe jako pierwszy argument

Wyjaśnienie

(s, r, f=0)                                  //Gets string, declares r and f to equal undefined and 0
         =>
            s.split``                        //Splits string into character array
            .map(                            //Loops over array
                 (l, i)=>(
                         f +=                //Increment f
                         l=='(' ? 1 : -1,    //By either 1 or -1 depending on character
                         f<0 ?               //If the floor is less than 0
                         r=r||++i            //And is first time below, r equals index (+1 to make it '1 indexed not 0')
                         : 0)
                         &&r                   //Return index
odnawiać
źródło
0

Python (3.5), 78 71 62 bajtów

rozwiązanie rekurencyjne

f=lambda s,p=0,v=0:p if v<0else f(s[1:],p+1,v+2*(s[0]<')')-1) 

jest podobny do tego rozwiązania dla minigolfa

możemy założyć, że Święty Mikołaj zawsze dotrze do piwnicy

Erwan
źródło