Conversor ternário-se


18

Em Java / .NET / C / JavaScript / etc. você pode usar ifs ternários para reduzir as instruções if.

Por exemplo (em Java):

// there is a String `s` and an int `i`
if(i<0)s="Neg";else if(i>0)s="Pos";else s="Neut";

Pode ser encurtado com um termo ternário para:

s=i<0?"Neg":i>0?"Pos":"Neut";

Desafio:

Entrada: um if-else regular (possível com aninhamento) que define uma única variável.

Saída: o ternário-se convertido.

Regras do desafio:

  • Você pode assumir que todos os casos if-else são possíveis sem colchetes (portanto, cada bloco if / else-if / else possui um único corpo).
  • Você pode assumir que não haverá espaços, tabulações ou novas linhas, exceto um espaço após cada um else(inclusive às else if).
  • Você pode assumir que os nomes das variáveis ​​usadas são sempre uma única letra minúscula ( [a-z]).
  • Os valores dados às variáveis ​​podem ser um dos seguintes:
    • Cordas (sem espaços / separadores / novas-linhas), que serão rodeadas por aspas (isto é "Test", "SomeString", "Example_string", etc.). Você pode assumir que as seqüências nunca conterão as substrings ifou elsenem espaços, tabulações, novas linhas, aspas duplas (com escape) ou o caractere =. Ele pode conter os caracteres ><(){}[];?:!&|, mas estará apenas no intervalo ASCII imprimível ( ['!' (33), '~' (126)]).
    • Inteiros (isto é 0, 123, -55, etc.)
    • Decimais (isto é 0.0, 0.123, -55.55, etc.)
  • Os valores nunca serão misturados. Portanto, todas as variáveis ​​atribuídas são números inteiros, e algumas não são números inteiros e outras são strings.
  • As condições dentro de parêntesis podem conter os seguintes caracteres =<>!+-/*%&|[], a-z, 0-9. Você pode assumir que não haverá parênteses internos e também pode assumir que não haverá campos (confusos) de mais de um caractere usado (como if(if<0)).
  • Você pode assumir que não haverá atalhos como, em i*=10vez de i=i*10.
  • Você não precisará lidar com elsecasos pendentes , para que todos ifpossam ser combinados com um else. Ou if(a)if(b)r=0;else r=1;seja, não é um caso de entrada possível. if(a)if(b)r=0;else r=1;else r=2;ou if(a&&b)r=0;else if(a&&!b)r=1;else r=-1;são, no entanto.
  • A E / S é flexível. Entrada e Saída pode ser uma sequência, lista de caracteres, leitura de STDIN, saída para STDOUT, etc. Sua chamada.
  • Todos os ternários terão uma associatividade correta, como é o padrão na maioria dos idiomas ( mas não no PHP, por exemplo ).

Regras gerais:

  • Isso é , então a resposta mais curta em bytes vence.
    Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação.
  • As regras padrão se aplicam à sua resposta, para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados e programas completos do tipo retorno. Sua chamada.
  • As brechas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código.
  • Além disso, adicione uma explicação, se possível.

Casos de teste:

Input:   if(i<0)s="Neg";else if(i>0)s="Pos";else s="Neut";
Output:  s=i<0?"Neg":i>0?"Pos":"Neut";

Input:   if(i%2<1)r=10;else r=20;
Output:  r=i%2<1?10:20;

Input:   if(n<10)if(m<0)i=0;else i=10;else if(m<0)i=-1;else i=1;
Output:  i=n<10?m<0?0:10:m<0?-1:1;

Input:   if(i==1)i=0.0;else i=0.25;
Output:  i=i==1?0.0:0.25;

Input:   if(!a)if(b)r=0;else r=1;else r=2;
Output:  r=!a?b?0:1:2;

Input:   if(a)if(b)r=0;else r=1;else if(c)r=2;else r=3;
Output:  r=a?b?0:1:c?2:3;

Input:   if(a&&b)r=0;else if(a&&!b)r=1;else r=-1;
Output:  r=a&&b?0:a&&!b?1:-1;

Input:   if(i[0]>0)if(j>0)if(q>0)r="q";else r="j";else r="i";else r="other";
Output:  r=i[0]>0?j>0?q>0?"q":"j":"i":"other";

Input:   if(i>0)r="i";else if(j>0)r="j";else if(q>0)r="q";else r="other";
Output:  r=i>0?"i":j>0?"j":q>0?"q":"other";

Input:   if(a>0)if(a<2)x="one";else if(a<3)x="two";else if(a<4)x="three";else x="other";else x="other";
Output:  x=a>0?a<2?"one":a<3?"two":a<4?"three":"other":"other";

Input:   if(b[0]<=b[1])q=5;else if(b[0]==null)q=0;else q=-10;
Output:  q=b[0]<=b[1]?5:b[0]==null?0:-10;

Tecnicamente, em F # if ... then ... elseé o operador ternário. Então, se você escrever let result = if 10 > 100 then 99 else -99, o valor de resultseria -99.
Ciaran_McCarthy

1
@Ciaran_McCarthy Eu esperaria que esse fosse o caso da maioria, se não de todas as linguagens funcionais que têm expressões condicionais como padrão. Clojure, Scala e Haskell são os mesmos.
Carcigenicate

@tsh Ops .. Eu não devo adicionar casos de teste tarde da noite após um dia de trabalho .. Corrigido.
Kevin Cruijssen 10/10

2
O compilador de fechamento de compressor JavaScript funciona muito bem em todos esses casos de teste. Que, ao receber as entradas fornecidas, geraria apenas as saídas esperadas. Mas parece que não posso reivindicá-lo como resposta. Então, eu gostaria de comentar aqui.
TSH

Respostas:


5

Retina 0.8.2 , 32 bytes

+r`if.(.*?)\)(.=)
$2$1?
;.{6}=
:

Experimente online! Explicação:

r`if.(.*?)\)(.=)
$2$1?

Manuseie um ifimediatamente antes de uma atribuição movendo a atribuição antes da condição e anexando a ?. O estágio é correspondido da direita para a esquerda para garantir que chegamos o mais próximo possível da tarefa, enquanto \)garante que não correspondemos elsepor engano.

+

Repita o estágio para cuidar de ifs aninhados .

;.{6}=
:

Quaisquer atribuições restantes são elses, então substitua ;else ?=por a :.


@nwellnhof Obrigado por apontar isso; Eu pensei que estava jogando um byte por lá porque funcionava nos casos de teste.
911 Neil

6

Python 2 , 126 121 120 114 100 bytes

lambda s:findall(' (.=)',s)[0]+sub('if.(.*?)\)(.=)?',r'\1?',sub('.{5} (.=)?',':',s))
from re import*

Experimente online!


Salvou:

  • -1 byte, graças a Kevin Cruijssen

@KevinCruijssen Thanks :) #
TFeld 9/10

1
Por que a definição de função é anterior à importação?
Skyler

@Skyler ele realmente não importa, mas é mais fácil colocar a atribuição no cabeçalho desta forma
Jo Rei

6

Perl 5 -p, 50 49 48 bytes

s/if.(.*?)\)(.=)/\2\1?/g;s/.if./?/g;s/;.{6}=/:/g

Experimente online!

A versão de 48 bytes é inspirada na resposta Retina de Neil.

Explicação

# Replace "if(e1)if(e2)x=" with "x=e1)if(e2?"
s/if.(.*?)\)(.=)/\2\1?/g;
# Replace ")if(" with "?"
s/.if./?/g;
# Replace ";else x=" with ":"
s/;.{6}=/:/g

Solução antiga de 49 bytes

s/.{5} (.=)?/:/g;s/if.(.*?)\)(.=)?/\1?/g;$_=$2.$_


3

Java (JDK) , 119 116 bytes

Solução regex quase totalmente pura, cortada e alterada um pouco em algumas das outras respostas.

-3 bytes graças a mais alguns truques de regex de Kevin

s->s.replaceAll(".*(.=).*","$1$0").replaceAll("if.(.*?)\\)","$1?").replaceAll("([ ?]).=","$1").replace(";else ",":")

Experimente online!

Explicação

s->                                         // Lambda function taking a String
   s.replaceAll(".*(.=).*","$1$0")          // Find assigned variable and append to start of String
    .replaceAll("if.(.*?)\\)","$1?")        // Replace any 'if' statements with their condition
                                            // followed by '?'
    .replaceAll("([? ]).=","$1")            // Remove all assignments after a '?' or space
    .replace(";else ",":");                 // Simple replace (no regex) to remove 'else' statements

1
Gosto do ".*(.=).*","$1$0"que você usou, é 1 byte menor que o que "^(.*)(.=)","$2$1"eu tinha em mente. :) De qualquer forma, você pode salvar 2 bytes mudando if\\(para if.e um byte adicional mudando (\\?| )para ([? ]). Experimente online 116 bytes .
Kevin Cruijssen 9/10/1918

@KevinCruijssen Cheers! Passei tanto tempo tentando reduzir a expressão regular, não acredito que perdi isso!
Luke Stevens

3

Kakoune v2018.09.04 , 43 38 37 bytes

xs\w=(?!=)<ret>d<a-h>Psif.<ret>df);r?xs;else<space><ret>c:<esc>

Explicação:

Kakoune é um editor modal baseado em seleção múltipla, inspirado no Vim.

  1. x selecione a linha inteira

  2. s... <ret>filtre a seleção com a expressão regular \w=(?!=), que corresponde a todas as atribuições de variáveis ​​e não corresponde às ==comparações

  3. d exclua cada seleção e coloque seu conteúdo no registro padrão

  4. <a-h> estender todas as seleções para o início de sua linha

  5. P cole o conteúdo do registro padrão antes de cada seleção

  6. s... <ret>filtre a seleção com a expressão regularif.

  7. d excluir cada seleção

  8. f estender cada seleção para a próxima )

  9. ; reduza cada seleção ao seu cursor

  10. r substitua cada caractere de cada seleção por ?

  11. x selecione a linha inteira

  12. s... <ret>filtre a seleção com;else<space>

  13. c... <esc>limpe cada seleção e substitua-a por:

animação do código em um caso de teste:

Código em ação


1
Hmm, eu nunca ouvi falar de Kakoune antes. Eu acho que não há nenhum compilador online para isso? Caso contrário, você poderia adicionar algumas capturas de tela de alguns dos casos de teste para que eu possa verificar se funciona como pretendido? Além disso, se esse é o seu idioma, você pode entrar em contato com Dennis no chat talk.tryitonline.net para perguntar se ele pode adicioná-lo ao TIO .
Kevin Cruijssen

1
@KevinCruijssen Adicionei um gif de um dos casos de teste. Funciona em todos eles, mas criar gifs não é trivial.
Vaelus

Obrigado pela explicação e gif, +1 de mim. :) É sempre bom aprender sobre um novo idioma.
Kevin Cruijssen 9/10/1918

2

Limpos , 386 375 216 196 189 bytes

Olha ma, sem regex!

import StdEnv,Data.List
?[_,'=':b]= $b
?b= $b
$['if(':s]#(h,[_:t])=span((<>)')')s
=h++['?': ?t]
$[';else ':s]=[':': ?s]
$[a:b]|b>[]=[a: $b]=b
@s=hd[[v,e: $s]\\['else ',v,e=:'=':_]<-tails s]

Experimente online!


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.