Преобразователь троичного-ифа


18

В Java / .NET / C / JavaScript / и т. Д. Вы можете использовать троичные-ifs для сокращения if-операторов.

Например (на Java):

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

Можно укоротить на троицу, если:

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

Вызов:

Входные данные: обычный if-else (возможно с вложением), который устанавливает одну переменную.

Выход: преобразованный троичный-если.

Правила соревнований:

  • Вы можете предположить, что все случаи if-else возможны без скобок (поэтому каждый блок if / else-if / else имеет одно тело).
  • Вы можете предположить, что не будет пробелов, табуляции или новых строк, за исключением одного пробела после каждого else(включая at else if).
  • Вы можете предположить, что используемые имена переменных всегда состоят из одной строчной буквы ( [a-z]).
  • Значения, данные переменным, могут быть одним из:
    • Строки (без пробелов / вкладки / новая строка), которые будут окружены двойными кавычками (например "Test", "SomeString", "Example_string"и т.д.). Вы можете предположить, что строки никогда не будут содержать подстрок ifили else, и при этом они не будут содержать пробелы, табуляции, новые строки, (экранированные) двойные кавычки или символ =. Он может содержать символы ><(){}[];?:!&|, но будет только в диапазоне ASCII для печати ( ['!' (33), '~' (126)]).
    • Целые (то есть 0, 123, -55и т.д.)
    • Десятичные (то есть 0.0, 0.123, -55.55и т.д.)
  • Значения никогда не будут смешаны. Таким образом, все назначенные переменные являются целыми числами, а некоторые не являются целыми числами, а некоторые являются строками.
  • Условия в круглых скобках может содержать следующие символы =<>!+-/*%&|[], a-z, 0-9. Вы можете предположить, что не будет никаких внутренних скобок, и вы также можете предположить, что не будет никаких (сбивающих с толку) полей из более чем одного используемого символа (например if(if<0)).
  • Вы можете предположить, что не будет никаких ярлыков, как i*=10вместо i=i*10.
  • Вам не придется обрабатывать висячие elseслучаи, так что все ifможет быть в паре с else. Т.е. if(a)if(b)r=0;else r=1;это не возможный случай ввода. if(a)if(b)r=0;else r=1;else r=2;или if(a&&b)r=0;else if(a&&!b)r=1;else r=-1;однако.
  • Ввод / вывод является гибким. Ввод и вывод может быть строкой, списком символов, считыванием из STDIN, выводом в STDOUT и т. Д. Ваш вызов.
  • Все троицы будут иметь правильную ассоциативность, как это принято в большинстве языков ( но не в, например, PHP ).

Основные правила:

  • Это , поэтому выигрывает самый короткий ответ в байтах.
    Не позволяйте языкам кода-гольфа отговаривать вас от публикации ответов на языках, не относящихся к кодексу. Попробуйте придумать как можно более короткий ответ для «любого» языка программирования.
  • К вашему ответу применяются стандартные правила , поэтому вы можете использовать STDIN / STDOUT, функции / метод с правильными параметрами и типом возврата, полные программы. Ваш звонок.
  • По умолчанию лазейки запрещены.
  • Если возможно, добавьте ссылку с тестом для вашего кода.
  • Также, пожалуйста, добавьте объяснение, если это возможно.

Тестовые случаи:

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;

Технически в F # if ... then ... elseэто троичный оператор. Так что если вы напишите, let result = if 10 > 100 then 99 else -99то значение resultбудет -99.
Ciaran_McCarthy

1
@Ciaran_McCarthy Я ожидаю, что так будет с большинством, если не со всеми функциональными языками, в которых условные выражения используются по умолчанию. Clojure, Scala и Haskell - это одно и то же.
Carcigenicate

@tsh Упс .. Я не должен добавлять тестовые случаи поздно вечером после рабочего дня .. Исправлено.
Кевин Круйссен

2
JavaScript Compressor Closure Compiler прекрасно работает на всех этих тестовых примерах. Который при принятии данных входов будет просто генерировать ожидаемые результаты. Но, похоже, я не могу претендовать на это как на ответ. Поэтому я хотел бы прокомментировать здесь.
TSH

Ответы:


5

Сетчатка 0.8.2 , 32 байта

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

Попробуйте онлайн! Объяснение:

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

Обработайте ifнепосредственно перед назначением, переместив назначение перед условием и добавив a ?. Этап сопоставляется справа налево, чтобы гарантировать, что мы получим, если ближе всего к назначению, в то время как \)гарантирует, что мы не совпадаем elseпо ошибке.

+

Повторите этап, чтобы заботиться о вложенных ifс.

;.{6}=
:

Все остальные присвоения elseей так заменить ;else ?=с :.


@nwellnhof Спасибо за указание на это; Я думал, что играю в байт там, потому что это сработало на тестовых примерах.
Нил

6

Python 2 , 126 121 120 114 100 байт

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

Попробуйте онлайн!


Добавлено:

  • -1 байт, спасибо Кевину Круйссену

@KevinCruijssen Спасибо :)
TFeld

1
Почему определение функции перед импортом?
Скайлер

@Skyler На самом деле это не имеет значения, но легче поместить это назначение в заголовок таким образом
Джо Кинг,

6

Perl 5 -p, 50 49 48 байтов

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

Попробуйте онлайн!

48-байтовая версия основана на ответе Нейла Retina.

объяснение

# 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

Старое 49-байтовое решение

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


3

Java (JDK) , 119 116 байт

Почти полностью чистое решение для регулярных выражений, отрубленное и немного измененное из пары других ответов.

-3 байта, благодаря еще одному трюку с регулярными выражениями от Кевина

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

Попробуйте онлайн!

объяснение

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
Мне нравится, что ".*(.=).*","$1$0"вы использовали, это на 1 байт короче, чем "^(.*)(.=)","$2$1"я имел в виду. :) В любом случае, вы можете сохранить 2 байта, изменяя if\\(на, if.и дополнительный байт, изменяющийся (\\?| )на ([? ]). Попробуйте онлайн 116 байт .
Кевин Круйссен

@KevinCruijssen Приветствия! Я потратил так много времени, пытаясь свести на нет регулярное выражение, я не могу поверить, что пропустил это!
Люк Стивенс

3

Kakoune v2018.09.04 , 43 38 37 байтов

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

Объяснение:

Kakoune - модальный редактор с множественным выбором, вдохновленный Vim.

  1. x выбрать всю строку

  2. s... <ret>фильтровать выделение с помощью регулярного выражения \w=(?!=), которое соответствует всем назначениям переменных и не соответствует ==сравнениям

  3. d удалить каждый выбор и поместить его содержимое в регистр по умолчанию

  4. <a-h> расширить все выборки до начала их строки

  5. P вставлять содержимое регистра по умолчанию перед каждым выбором

  6. s... <ret>отфильтровать выделение с помощью регулярного выраженияif.

  7. d удалить каждый выбор

  8. f расширить каждый выбор вперед к следующему )

  9. ; уменьшить каждый выбор до его курсора

  10. r заменить каждый символ каждого выбора на ?

  11. x выбрать всю строку

  12. s... <ret>отфильтруйте выбор с помощью;else<space>

  13. c... <esc>очистить каждый выбор и заменить его:

анимация кода на тестовом примере:

Код в действии


1
Хм, я никогда не слышал о Какуне раньше. Я думаю, что для этого нет онлайн-компилятора? Если нет, то не могли бы вы добавить несколько скриншотов некоторых тестовых случаев, чтобы я мог убедиться, что они работают как задумано? Кроме того, если это ваш язык, вы можете связаться с Деннисом в чате talk.tryitonline.net и спросить, может ли он добавить его в TIO .
Кевин Круйссен

1
@KevinCruijssen Я добавил gif одного из тестовых случаев. Это работает на всех из них, но делать гифки не тривиально.
Vaelus

Спасибо за объяснение и GIF, +1 от меня. :) Всегда приятно учить новый язык.
Кевин Круйссен

2

Чистый , 386 375 216 196 189 байт

Смотри, мама, нет регулярных выражений!

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]

Попробуйте онлайн!


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.