Acessórios após o fato!

10

Esse desafio é inspirado na matemática, é fato. Programação não é .


A notação matemática para um fatorial ou um fato é um ponto de exclamação !. O ponto de exclamação também é um símbolo comum notem muitas linguagens de programação.

Desafio:

Pegue uma sequência, contendo números e os caracteres: + !como entrada e saída, o seguinte:

Tudo na frente de um ponto de exclamação deve ser avaliado como uma expressão matemática, assim 2+2seria 4.

Tudo depois de um único ponto de exclamação deve ser anexado como acessório ao que estiver à sua frente, portanto: 2+2!5deve fornecer 45, porque 2+2=4e 5é um acessório. 2+2!5+5deve dar 410.

Como !também significa not, qualquer coisa que não seja um acessório após o fato não deve ser anexada. Então, 2+2!!5deve dar 4, já que 5não é um acessório. Agora, not(not(true))==trueentão 2+2!!!5deve dar 45. 2+2!!5!5+5deve dar:, 410porque 2+2=4, então seguido por um fatorial e !5!5+5. O primeiro 5não é um fato, mas 5+5está atrás de outro ponto de exclamação e, portanto, é um fato, mais uma vez.

Esclarecimentos:

  • Os pontos de exclamação não serão adjacentes a um +dos lados.
  • Não será levando +para os números (é 5, não +5).
  • Opcionalmente, você pode incluir um zero à esquerda se esse for o resultado da expressão antes do primeiro !. Ambos 4e 04saída aceita para entrada:0+0!4

Resumo executivo: avalie cada soma (tratando !como separadores). Em seguida, descarte todos os números que aparecerem após um número par de !(contados desde o início da sequência). Depois remova tudo !.

Casos de teste:

!
   <- Empty string

5
5

12!
12

!87
87

!!5
   <- Empty string

5+5!2+2
104

5+5!!2+2
10

1!2!3!4!5!6!7!8!9
12468

10+10!!2+2!!3+3!4+4
208

2!!3!5
25

2!!3!5!7
25

10!!!!!!!5
105

Isso é e o código mais curto em bytes (em cada idioma) vence! As explicações são fortemente encorajadas!

Stewie Griffin
fonte
umm ... digamos que temos 2 !! 3! 5 aqui é ou não 5 um acessório de 3?
officialaimm
3
@officialaimm É 25(veja o caso de teste adicionado). Mais importante 2!!3!5!7ainda daria 25, porque existe um número par de !esquerdas do 7(para que você não conte apenas a corrida na frente do número, mas toda a !esquerda dele).
Martin Ender
A saída pode ser um Mathematica Row?
Ngenisis
Hum ... então esse desafio realmente não tem nada a ver com fatoriais?
DLosc 18/02/19

Respostas:

5

Retina , 35 31 29 bytes

Economizou 4 bytes, inspirando-se nos produtos ETH .

Agradecemos a Leo por salvar outros 2 bytes.

\d+|\+
$*
1+
$.&
1`!

!\d*!?

Experimente online!

Martin Ender
fonte
Você pode salvar alguns bytes nas últimas linhas como esta
Leo
11
@ Leo Isso é realmente legal, obrigado. :)
Martin Ender
5

JavaScript (ES6), 58 56 bytes

Economizou dois bytes graças a Martin Ender .

let f =
x=>x.replace(/[^!]+/g,eval).replace(/!(\d*)!?\d*/g,"$1")
<input value="2+2!5+5" oninput="try{O.value=f(value)}catch(e){}"><br>
<input id=O value="410" disabled>

Pode ser melhorado de alguma forma ...

ETHproductions
fonte
Bom uso do argumento de função para replace.
Neil
@ Neil Obrigado, mas eu encontrei uma maneira melhor :-)
ETHproductions
Seu snippet de código está me dando a resposta errada 1+1!5. Eu acho que você esqueceu evalum pouco antes da !.
Value Ink
@ ValueInk Ah, caramba, não acho que exista uma maneira fácil de corrigir isso.
ETHproductions
2

Gelatina , 16 bytes

ṣ”!µḢW;m2$VṾ$L¡€

Experimente online!

Explicação

A observação principal aqui é que podemos executar as etapas "fora de ordem"; em vez de avaliar as somas e depois ignorar as que não gostamos, podemos ignorar as somas em posições inválidas e depois avaliar o restante.

ṣ”!µḢW;m2$VṾ$L¡€
ṣ”!                Split input on '!'
   µ               Set as the new default for missing arguments
    Ḣ              Take the first element, removing it from the default
     W;  $         Cons with
       m2            every odd-numbered element of {the tail of the !-split input}
               €   For each remaining element
          VṾ$      Evaluate and de-evaluate it
             L¡      a number of times equal to its length

Avaliar uma soma como "10+10"a avaliará em um número, por exemplo 20, desvalorizá-lo em uma sequência "20",. Repetir esse processo não tem efeito adicional (é idempotente). Assim, avaliamos efetivamente todos os elementos da string, exceto a string nula, que permanece sem avaliação porque possui um comprimento zero.


fonte
Esse é um ótimo truque para avaliar condicionalmente cada item. Você poderia, de alguma forma, pegar o AND lógico de cada item e seu valor de avaliação? (I assumir a cadeia vazia é Falsas em geléia)
ETHproductions
@ETHproductions: a testemunha de Jelly dificilmente salvaria bytes; prefere evitar usar o mesmo valor duas vezes, se possível, e se você deseja reutilizar um valor, normalmente precisa colocar pelo menos um extra µem algum lugar (e µnão funciona dentro de um loop, o que significa que você precisaria de algo ainda mais detalhado). Eu consegui fazê-lo funcionar como ṣ”!µḢW;m2$ȧVṾ$$€, mas não é mais curto (e tem a característica acumulação de cifrões que tendem a acontecer quando você empurra o Jelly para o limite de sua capacidade de aninhar estruturas de controle.)
2

Geléia , 18 bytes

ṣ”!µḊm2;@ḢW$LÐfVṾ€

Experimente online!

Como?

ṣ”!µḊm2;@ḢW$LÐfVṾ€ - Main link: string
ṣ”!                - split on '!' characters
   µ               - monadic chain separation (call that x)      e.g. ['1+1','0+0','0+0','0+0','','1+0','','','']
    Ḋ              - dequeue x (all but the leftmost entry of x) e.g.       ['0+0','0+0','0+0','','1+0','','','']
     m2            - modulo 2 index into that result             e.g.       ['0+0',      '0+0',   '1+0',   '']
           $       - last two links as a monad
         Ḣ         -     head x (the leftmost entry of x)        e.g.  '1+1'
          W        -     wrap                                    e.g. ['1+1']
       ;@          - concatenate with reversed arguments         e.g. ['1+1','0+0',      '0+0',   '1+0',   '']
             Ðf    - filter keep:
            L      -     length (keep that have non-zero length) e.g. ['1+1','0+0',      '0+0',   '1+0']
               V   - eval as jelly code (vectorises)             e.g. [  2,    0,          0,       1]
                      Yes, addition is just + and decimal numbers are just strings of digits in Jelly believe it or not!
                Ṿ€ - uneval €ach (creates a string from each one)e.g. [ '2',  '0',        '0'     ,'1']
                      without the € it would uneval the list and hence yield commas too)
                   - implicit print (prints the resulting list [of characters and possibly
                      lists of characters] as if it were all one string.)
Jonathan Allan
fonte
Eu não acho que isso funcione literalmente 0+0no meio da entrada (em um local onde não está sendo descartado); ele produz a cadeia nula, mesmo que deva produzir um dígito 0. #
Ah, é verdade - eu vou ter que mover-se para uma solução de longo :(
Jonathan Allan
Deve ser consertado (possivelmente jogável agora).
Jonathan Allan
1

Ruby , 58 56 + 1 = 59 57 bytes

Usa a -pbandeira. -2 bytes de Tutleman .

i=0;$_=' '+$_;gsub(/!?([^!]*)/){eval$1if(2>i+=1)||i%2<1}

Experimente online! (Uma linha extra de código foi adicionada para que ele pegasse todas as linhas de entrada e imprimisse a saída em linhas diferentes.)

Value Ink
fonte
Eu acho que você pode soltar os parênteses eval$1, não?
Tutleman
@Tutleman huh. Não sei qual o problema que estava tendo que me fez adicionar os parênteses (eles não estavam presentes quando comecei a escrever o programa), mas parece que realmente posso descartá-los.
Value Ink
0

Lote, 192 184 bytes

@echo off
set/ps=
call:c . "%s:!=" "%"
echo(%s%
exit/b
:c
set s=
if not %2=="" set/as=%2
:l
shift
shift
if "%1"=="" exit/b
if %1=="" goto l
set/at=%1
set s=%s%%t%
goto l

Ter que lidar com as cordas vazias é inconveniente.

Neil
fonte
0

Pip , 18 bytes

Eu acho que é o mais curto possível ... embora eu tenha dito isso há três iterações atrás também.

{VaX++v%2+!v}Ma^'!

Recebe entrada como argumento da linha de comando. Experimente online!

Explicação

                    a is 1st cmdline arg; global variable v is -1 (implicit)
              a^'!  Split a on !
{           }M      Map this function to the resulting list (note that inside function,
                    a is the function arg):
    ++v              Increment v (so that v tracks the 0-based index of the current
                     element)
       %2            We want to keep the elements where v%2 is 1...
         +!v         ... and also v=0, where v%2 is 0, but adding !v makes it 1
  aX                 String-multiply the argument by the above quantity (turning elements
                     we don't want into empty string)
 V                   Eval it (eval'ing empty string gives nil, but that's okay because
                     nil doesn't output anything)
                    Autoprint the resulting list, concatenated together (implicit)
DLosc
fonte
0

R, 95 bytes

function(x)for(e in strsplit(gsub('!([^!]*)![^!]*','\\1!',x),'!')[[1]])cat(eval(parse(text=e)))

Provavelmente, há algum espaço para melhorias, mas no momento é o melhor que posso apresentar.

Robert Hacken
fonte