Convertitore Ternary-if


18

In Java / .NET / C / JavaScript / ecc. puoi usare ternary-ifs per abbreviare if-statement.

Ad esempio (in Java):

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

Può essere abbreviato con un ternario, se a:

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

Sfida:

Input: un if-else regolare (possibile con annidamento) che imposta una singola variabile.

Output: il ternary-if convertito.

Regole della sfida:

  • Puoi presumere che tutti i casi if-else siano possibili senza parentesi (quindi ogni blocco if / else-if / else ha un solo corpo).
  • Puoi presumere che non ci saranno spazi, tabulazioni o nuove righe, ad eccezione di uno spazio singolo dopo ciascuno else(incluso at else if).
  • Puoi presumere che i nomi delle variabili utilizzati siano sempre una singola lettera minuscola ( [a-z]).
  • I valori dati alle variabili possono essere uno di:
    • Stringhe (spazi / schede / nuovo-linee), che sarà circondato da virgolette (cioè "Test", "SomeString", "Example_string", ecc). Puoi presumere che le stringhe non conterranno mai le sottostringhe ifo else, né conterranno spazi, tabulazioni, newline, virgolette doppie (con escape) o il carattere =. Può contenere i caratteri ><(){}[];?:!&|, ma sarà solo nell'intervallo ASCII stampabile ( ['!' (33), '~' (126)]).
    • Interi (cioè 0, 123, -55, etc.)
    • Decimali (cioè 0.0, 0.123, -55.55, etc.)
  • I valori non saranno mai mescolati. Quindi tutte le variabili assegnate sono numeri interi e non alcune sono numeri interi e alcune sono stringhe.
  • Le condizioni all'interno parentesi possono contenere i seguenti caratteri =<>!+-/*%&|[], a-z, 0-9. Puoi presumere che non ci sarà alcuna parentesi interna e puoi anche supporre che non ci saranno campi (confusi) con più di un personaggio usato (come if(if<0)).
  • Puoi presumere che non ci saranno scorciatoie come i*=10invece di i=i*10.
  • Non dovrai gestire i elsecasi penzoloni , quindi tutto ifpuò essere abbinato a un else. Cioè if(a)if(b)r=0;else r=1;non è un possibile caso di input. if(a)if(b)r=0;else r=1;else r=2;o lo if(a&&b)r=0;else if(a&&!b)r=1;else r=-1;sono comunque.
  • L'I / O è flessibile. Input e Output possono essere una stringa, un elenco di caratteri, letti da STDIN, output su STDOUT, ecc. La chiamata.
  • Tutti i ternari avranno una giusta associatività, come lo standard nella maggior parte delle lingue ( ma non in PHP ad esempio ).

Regole generali:

  • Questo è , quindi vince la risposta più breve in byte.
    Non lasciare che le lingue di code-golf ti scoraggino dal pubblicare risposte con lingue non codegolfing. Prova a trovare una risposta il più breve possibile per "qualsiasi" linguaggio di programmazione.
  • Per la tua risposta valgono regole standard , quindi puoi usare STDIN / STDOUT, funzioni / metodo con i parametri corretti e tipo di ritorno, programmi completi. La tua chiamata.
  • Sono vietate le scappatoie predefinite .
  • Se possibile, aggiungi un link con un test per il tuo codice.
  • Inoltre, si prega di aggiungere una spiegazione, se possibile.

Casi test:

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, in F # if ... then ... elseè l'operatore ternario. Quindi se scrivi let result = if 10 > 100 then 99 else -99allora il valore di resultsarebbe -99.
Ciaran_McCarthy,

1
@Ciaran_McCarthy Mi aspetto che ciò avvenga per la maggior parte, se non per tutti i linguaggi pendenti funzionali che hanno espressioni condizionali come impostazione predefinita. Clojure, Scala e Haskell sono gli stessi.
Carcigenicato

@tsh Oops .. Non dovrei aggiungere casi di test a tarda sera dopo una giornata di lavoro .. Risolto.
Kevin Cruijssen,

2
Il compilatore di chiusura del compressore JavaScript funziona perfettamente su tutti questi test. Che quando si prendono gli input dati genererebbero solo gli output previsti. Ma sembra che non posso rivendicarlo come una risposta. Quindi vorrei commentare qui.
TSH

Risposte:


5

Retina 0.8.2 , 32 byte

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

Provalo online! Spiegazione:

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

Gestisci ifimmediatamente prima di un compito spostando il compito prima della condizione e aggiungendo a ?. Lo stage è abbinato da destra a sinistra per assicurarci di ottenere il se più vicino al compito, mentre \)assicura che non abbiniamo elseper errore.

+

Ripeti lo stage per occuparti dei messaggi nidificati if.

;.{6}=
:

Eventuali incarichi rimanenti sono elses, quindi sostituisci ;else ?=con a :.


@nwellnhof Grazie per averlo sottolineato; Pensavo di giocare a golf un byte lì perché funzionava sui casi di test.
Neil,

6

Python 2 , 126 121 120 114 100 byte

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

Provalo online!


Salvato:

  • -1 byte, grazie a Kevin Cruijssen

@KevinCruijssen Grazie :)
TFeld

1
Perché la definizione della funzione è prima dell'importazione?
Skyler,

@Skyler In realtà non importa, ma è più facile inserire il compito nell'intestazione in questo modo
Jo King

6

Perl 5 -p, 50 49 48 byte

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

Provalo online!

La versione a 48 byte si ispira alla risposta di Retina di Neil.

Spiegazione

# 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

Vecchia soluzione da 49 byte

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

3

Rubino , 72 71 byte

->s{$a=$2while s.gsub!(/if.(.*?)\)(.=)?(.*?);\w* (.=)?/,'\1?\3:');$a+s}

Provalo online!


O può essere ;elseo else può .{5}salvare un byte.
Kevin Cruijssen,

1
Grazie, ho trovato qualcosa di diverso con lo stesso effetto.
GB

3

Java (JDK) , 119 116 byte

Soluzione regex quasi del tutto pura, tritata e cambiata un po 'da un paio di altre risposte.

-3 byte grazie ad altri trucchi regex di Kevin

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

Provalo online!

Spiegazione

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
Mi piace quello ".*(.=).*","$1$0"che hai usato, è 1 byte più corto di quello "^(.*)(.=)","$2$1"che avevo in mente. :) In ogni caso, puoi salvare 2 byte cambiando if\\(in if.e un byte aggiuntivo cambiando (\\?| )in ([? ]). Provalo online 116 byte .
Kevin Cruijssen,

@KevinCruijssen Cheers! Ho passato così tanto tempo a cercare di sminuire la regex, non riesco a credere di averlo perso!
Luke Stevens,

3

Kakoune v2018.09.04 , 43 38 37 byte

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

Spiegazione:

Kakoune è un editor modale basato sulla selezione multipla, ispirato a Vim.

  1. x seleziona l'intera riga

  2. s... <ret>filtra la selezione con l'espressione regolare \w=(?!=), che corrisponde a tutte le assegnazioni di variabili e non corrisponde ai ==confronti

  3. d elimina ogni selezione e inserisce il suo contenuto nel registro predefinito

  4. <a-h> estende tutte le selezioni all'inizio della loro riga

  5. P incolla il contenuto del registro predefinito prima di ogni selezione

  6. s... <ret>filtra la selezione con l'espressione regolareif.

  7. d cancella ogni selezione

  8. f estendi ogni selezione in avanti alla successiva )

  9. ; riduci ogni selezione al suo cursore

  10. r sostituisci ogni carattere di ogni selezione con ?

  11. x seleziona l'intera riga

  12. s... <ret>filtra la selezione con;else<space>

  13. c... <esc>cancella ogni selezione e sostituiscila con:

animazione del codice su un caso di test:

Codice in azione


1
Hmm, non ho mai sentito parlare di Kakoune prima. Immagino non ci sia nessun compilatore online per questo? In caso contrario, potresti forse aggiungere alcuni screenshot di alcuni casi di test in modo da poter verificare che funzioni come previsto? Inoltre, se questa è la tua lingua, puoi contattare Dennis nella chat di talk.tryitonline.net per chiedere se può aggiungerlo a TIO .
Kevin Cruijssen,

1
@KevinCruijssen Ho aggiunto una gif di uno dei casi di test. Funziona su tutti, ma realizzare le gif non è banale.
Vaelus,

Grazie per la spiegazione e gif, +1 da me. :) Sempre bello conoscere una nuova lingua.
Kevin Cruijssen,

2

Pulito , 386 375 216 196 189 byte

Guarda mamma, niente 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]

Provalo online!


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.