Quando o Papai Noel entra no porão? (Dia 1 da COA)

20

Estou reproduzindo a segunda parte do primeiro dia do Advent of Code, com permissão do criador.

Papai Noel está tentando entregar presentes em um grande prédio de apartamentos, mas ele não consegue encontrar o andar certo - as instruções que recebeu são um pouco confusas. Ele começa no térreo (andar 0) e segue as instruções, um personagem de cada vez.

Um parêntese de abertura (significa que ele deve subir um andar e um parêntese de fechamento )significa que ele deve descer um andar.

O prédio é muito alto e o porão é muito profundo; ele nunca encontrará o piso superior ou inferior.

Dado um conjunto de instruções, encontre a posição do primeiro caractere que o leva a entrar no porão (piso -1).

Como exemplos:

entrada )faz com que ele entre no porão na posição 1 do personagem.

entrada ()())faz com que ele entre no porão na posição 5 do personagem.

Uma entrada longa é fornecida aqui que deve render a solução 1797.

Isso é código de golfe, então a solução mais curta vence!

A Simmons
fonte
Temos que usar esses caracteres exatos?
Blue
1
@muddyfish Nos desafios originais, os insumos eram dados de uma forma específica e, com frequência, uma parte essencial do desafio era analisar os insumos; Embora eu não queira que isso se torne um "problema camaleão", acho que o espírito do original é que a entrada deva ser uma sequência de colchetes. Sei que isso privilegia algumas línguas em detrimento de outras, mas exortaria os eleitores a levar isso em consideração ao atribuir votos positivos a soluções.
Um Simmons
Muito estreitamente relacionado a números binários parentificáveis ... Eu não me sinto suficientemente forte para ser um idiota, então deixarei um comentário.
AdmBorkBork 17/02
@ TimmyD Entendo o que você quer dizer, mas sinto que essa pergunta é diferente o suficiente para que as respostas competitivas não possam tirar muito proveito dessa pergunta!
Um Simmons
1
Estou tentando resolver isso no SMBF (basicamente BF), e essa linguagem SUGA para depurar ... ugh.
mbomb007

Respostas:

17

Geléia, 8 7 bytes

O-*+\i-

Graças ao @ Sp3000 por jogar fora 1 byte!

Experimente online!

Como funciona

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
fonte
16

Python 2, 44 bytes

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

Essa solução inteligente foi encontrada por hallvabo, xsot, mitchs e whatisgolf sobre esse problema no golfe da anarquia . Se algum de vocês quiser publicá-lo, removerei isso.

O truque é deixar o analisador do Python fazer o trabalho. A função input()tenta avaliar uma sequência de entrada e gera um erro no primeiro parêntese sem correspondência. Este erro, quando detectado, tem forma

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

que inclui o número do caractere em que o erro ocorreu.

xnor
fonte
7

Python, 79 77 bytes

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

Provavelmente existe uma maneira melhor de fazer isso, mas estou sem ideias. Também este é o meu primeiro post sobre codegolf.

Graças a @Erwan. para jogar fora de 2 bytes.

drobilc
fonte
Bem vindo ao site! Este é um primeiro post muito bom. :)
Alex A.
você pode substituir [0:g]por[:g]
Erwan
e esta substituição save 1 bytes eu acho que -2*ord(z)+81por2*(z<')')-1
Erwan
5

Python 3, 59

Economizou 3 bytes graças ao grc.

Eu realmente não gosto de fazer indexação manual de strings em Python. Parece tão errado.

def f(x):
 c=q=0
 while-~c:c+=1-(x[q]>'(')*2;q+=1
 return q
Morgan Thrapp
fonte
5

C, 55 bytes

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

Experimente aqui .

Edit: Não sei por que deixei uma variável não utilizada lá ...

Cole Cameron
fonte
5

CJam, 10 bytes

0l'_*:~1#)

ou

0l'_*~]1#)

ou (créditos para Dennis)

Wl+'_*:~1#

Teste aqui.

Explicação

Como A Simmons já observou, ()é uma escolha de sorte para o CJam, pois esses são os operadores de decremento / incremento, respectivamente. Isso significa que, se estamos começando do zero, estamos procurando a etapa em que o Papai Noel chega ao andar 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
fonte
4

Labirinto , 18 bytes

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

Experimente online! Esta resposta foi o resultado da colaboração com o @ MartinBüttner.

Explicação

O habitual Labirinto iniciador (eu digo "habitual", mas na verdade reescrevo isso toda vez):

  • Labyrinth é uma linguagem 2D baseada em pilha, com execução a partir do primeiro caractere válido (aqui, no canto superior esquerdo). Em cada junção, onde há dois ou mais caminhos possíveis para o ponteiro de instruções seguir, a parte superior da pilha é verificada para determinar para onde seguir. Negativo é virar à esquerda, zero é avançar e positivo é virar à direita.
  • A pilha está sem fundo e cheia de zeros, portanto, saltar de uma pilha vazia não é um erro.
  • Os dígitos no código-fonte não pressionam o número correspondente - em vez disso, eles aparecem no topo da pilha e pressionam n*10 + <digit>. Isso permite a fácil criação de grandes números. Para iniciar um novo número, use _, que empurra zero.

Esse código é um pouco estranho, pois, para fins de golfe, o loop principal combina duas tarefas em uma. Para a primeira metade da primeira passagem, eis o que acontece:

+(+             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

Agora que a pilha foi inicializada com -1 no topo, o processamento real pode começar. Aqui está o que o loop principal faz.

,               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

A última duplicata adiciona um elemento à pilha para cada iteração que realizamos. Isso é importante porque, quando atingimos zero e avançamos no NOP, fazemos:

#               Push stack depth
(               Decrement
!               Output as num
@               Terminate
Sp3000
fonte
3

Oracle SQL 11.2, 160 159 bytes

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;

Sem golfe

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
fonte
3

Retina ,22 21

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

Experimente online ou experimente o grande caso de teste. (O URL é grande para o grande caso de teste, deixe-me saber se ele quebra para você, parece bom no chrome.)

1 byte economizado graças ao Martin!

Combinamos o primeiro conjunto de parênteses balanceados e o extraímos, depois contamos o número de vezes que a sequência vazia corresponderá a esse resultado. Não tenho certeza se essa é a melhor maneira de fazer isso no Retina, principalmente se o modo PCRE o tornar mais curto, mas o uso da $#_substituição pareceu ser mais longo por causa de um erro e pelo problema de ter mais de uma correspondência.

Esse algoritmo causa um comportamento estranho para entrada inválida, essencialmente pressupõe que, se o Papai Noel não chegar ao porão, ele misteriosamente se teleporta para lá após os outros movimentos.

FryAmTheEggman
fonte
3

Grep + AWK, 51 bytes

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

O grepcomando coloca cada caractere em uma nova linha.

Robert Benson
fonte
3

Pitão, 13 bytes

f!hsm^_1Cd<zT

Explicação

              - 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)

Experimente aqui

Algoritmo antigo, 15 bytes

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

Explicação:

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

Experimente aqui

Ou, se for permitido o uso de caracteres diferentes de (e ), 9 bytes (movendo o pré-processamento para a entrada)

f!.v+<zT1

Explicação

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

Experimente aqui

Azul
fonte
3

JavaScript (ES6), 58 bytes

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

Funciona removendo recursivamente um par de ()s correspondentes até o primeiro caractere ser a ). Aviso: não tente fazer isso em strings que não possuem )s suficientes . Exemplo:

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

Neste ponto, vê que 12 caracteres foram excluídos no total, de modo que a resposta é 13.

Neil
fonte
Você pode colocar esse comentário em sua resposta.
Mbomb007
3

MATL , 12 11 bytes

1 byte salvo usando a ideia de computação de Dennis -1 aumentada para a string de entrada

1_j^Ys0<f1)

Experimente 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
fonte
2

CJam, 12 10 bytes

0q{~_}%1#)

Experimente aqui.

Dois bytes salvos graças a Martin.

Explicação:

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
A Simmons
fonte
2

Javascript, 117 bytes

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++;}

Ignora outros caracteres. Usos prompte alert.

Solomon Ucko
fonte
2

Perl, 34 + 1 = 35 bytes

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

Obrigado a Dennis por algumas dicas.

Corra com a -pbandeira. Ele funciona no Perl 5.10, mas as versões posteriores precisam de um espaço aqui:++ while

Versão mais antiga e não destruída:

$_ = <>;                # 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
fonte
2

Python, 44 bytes

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

O piso icomeça de 1forma que terminemos isendo o valor de falsey 0. Se não for finalizado, adicione recursivamente um ao resultado com o primeiro caractere removido e o número do andar atualizado com base nesse caractere.

xnor
fonte
2

Javascript, 57 bytes

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

Muito simples, apenas itera sobre a entrada, incs if '(' decs if ')'. Retorna na primeira negativa.

SethWhite
fonte
2

Ruby, 47 bytes

Função anônima.

->s{i,l=-1,0;l+=s[i+=1]>?(?-1:1 while l>-1;i+1}
Value Ink
fonte
1

C, 73 bytes

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

Espera entrada no STDIN; nenhum caractere que não seja (e )possa aparecer na entrada (pelo menos até chegarmos à resposta). A entrada deve ser ASCII.

Emite a resposta em STDOUT.

Usa a diferença de 1 bit entre o ASCII para (e ).

/* 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);
}

Versão bem formatada:

David Morris
fonte
Você pode mover a f=c=0inicialização do loop for(f=c=0;f!=...para salvar um byte?
AdmBorkBork 17/02
@ TimmyD melhor para torná-los globais para que sejam inicializados automaticamente.
Cole Cameron
1

PowerShell, 75 65 62 bytes

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

Usa uma técnica semelhante à dos números binários parentificáveis para percorrer todos os caracteres de entrada, mantendo uma $conça corrente de +1cada um (e -1de cada um )e testando se atingimos negativo (por exemplo, estamos no porão).

Edit - salvo 10 bytes por iteração sobre os personagens reais, em vez de seus índices
Editar 2 - salva 3 bytes adicionais por cheque igualdade trocando para modulo tão fundição está implícita

AdmBorkBork
fonte
1

Mathematica, 62 55 bytes

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

Todos os nomes de funções longos! Funciona de maneira semelhante à resposta CJam de Simmons.

LegionMammal978
fonte
1

Baixar 25 bytes

Saídas em unário. Isso o inicia no primeiro andar e vai até 0.

1<\1_v#:+-*2%2~
:#._@>$1>
MegaTom
fonte
1

Raquete (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)))))

Ungolfed

(λ (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
fonte
1

APL, 18 caracteres

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

Em inglês:

  • ¯1*')'=⍵: -1 onde input = ")", 1 caso contrário;
  • +\: soma em execução;
  • 1⍳⍨¯1=: encontre o índice do primeiro -1.
lstefano
fonte
1

Lua, 92 89 87 Bytes

Ele recebe um argumento da linha de comando.

Editar: salvos 3 bytes

Edit: salvou 2 bytes e corrigiu um bug que poderia ocorrer em casos extremos, agora ele sai via seu código de saída

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

Ungolfed

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
fonte
1

k / kona , 23 21 bytes

2 bytes salvos removendo parênteses desnecessários.

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

Uso:

k){1+(+\1 -1"()"?x)?-1} "())"
3
Simon Major
fonte
0

Perl, 40 + 1 = 41 bytes

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

Requer a -pbandeira:

$ 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

Pressupõe entrada válida.

Como funciona:

                                           # -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
fonte
0

Javascript (ES6), 68 67 bytes

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

Recebe entrada como primeiro argumento

Explicação

(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
reubn
fonte
0

Python (3.5), 78 71 62 bytes

uma solução recursiva

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

é semelhante a esta solução para minigolfe

podemos assumir que o Papai Noel sempre chega ao porão

Erwan
fonte