Унарные числа обычно представляют только неотрицательные целые числа, но мы можем расширить их, чтобы представить все целые числа следующим образом:
- Положительное целое число N представляется как N
1
:5 -> 11111
- Отрицательное целое число -N представляется как
0
N, за которыми следуют1
:-5 -> 011111
- Ноль представлен как
0
Затем мы можем однозначно представить список этих чисел, если будем использовать 0
в качестве разделителя:
3,-2,0,1
111,011,0,1
111 0 011 0 0 0 1
11100110001
Ваша задача: взять строку, представляющую такой список унарных чисел со знаком, и перевести ее в список десятичных чисел.
Детали
Вы можете предположить, что ввод представляет собой полный список унарных чисел со знаком. В частности, вашей программе не нужно обрабатывать 1) пустой ввод или 2) ввод, заканчивающийся разделителем.
Вы можете предположить, что величина каждого числа не будет превышать 127. Для языков с максимальными размерами строк или списков вы можете предполагать, что ввод и вывод будут соответствовать структуре данных вашего языка, но ваш алгоритм теоретически должен работать для списка любого размера.
Ваша программа или функция может выполнять ввод / вывод любым из стандартных способов . Входные данные могут быть строкой или списком символов, односимвольными строками, целыми числами или логическими значениями. Вы можете использовать любые два символа для представления 1
и 0
; если вы не используете1
и 0
, пожалуйста, укажите, какие символы вы используете.
Вывод должен быть десятичным числом в любом приемлемом формате списка (в частности, должен быть какой-то разделитель между числами). Отрицательные числа должны быть обозначены знаком минус, хотя если ваш язык имеет другой формат для отрицательных целых чисел, я также приму это. Ноль может быть представлен в выводе как 0
или -0
.
Контрольные примеры
1 -> 1
0 -> 0 (or -0, and similarly for the other test cases)
011 -> -2
1101 -> 2,1
1100 -> 2,0
11001 -> 2,-1
110001 -> 2,0,1
11100110001 -> 3,-2,0,1
00000001 -> 0,0,0,-1
01111011111111001111111111111110111111111111111100111111111111111111111110111111111111111111111111111111111111111111 -> -4,8,-15,16,-23,42
01111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 -> -127
'0's
, это не является технически унарным. Хороший вызов, хотя!0
) и префикс отрицательного знака (0
) одинаковы, хотя это по-прежнему однозначно, так как вы не можете иметь отрицательные знаки в середине числа (182--693-1
число? Нет, и ни1111011000101111
по одной и той же причине).Ответы:
Python 2 ,
7370 байтФункция, которая принимает строку в качестве входных данных и возвращает строковое представление списка Python. Ноль может быть представлен как
0
и-0
(когда это происходит последним):объяснение
split
входная строкаs
на нули.map
).Это займет у нас долгий путь. Нули были разделителями в конце концов. И числа были одинарными, поэтому
len
удобно конвертировать их в десятичные. Но теперь мы испортили все виды использования без разделителей0
. К счастью, все виды использования без разделителей были ведущими нулями, поэтому они шли после нулевого разделителя и дали нам строки нулевой длины ('00'.split('0') == ['', '', '']
). Эти строки нулевой длины также стали0
из-заlen
.replace
вместо этого каждый ноль, который предшествует другому числу с отрицательным знаком на этом числе. Это исправляет использование0
в качестве знака, но ломает буквальные нули. Буквальным нулям также предшествовал разделитель, поэтому они стали парами дополнительных тире на следующем числе.replace
каждый--
обратно в0
элемент в «списке».источник
Сетчатка ,
2321 байтПопробуйте онлайн!
Первый этап
(.)0<newline>$1<space>
соответствует любому персонажу, за которым следует0
. Матч заменяется первым символом, за которым следует пробел. Это разбивает строку по отдельным номерам.Второй этап
01<newline>-1
заменяет0
's перед блоком1
' s на-
знак.Последний этап
1+<newline>$.&
сопоставляет все блоки1
's' и заменяет их длиной группы.Вот пример с выводом отдельных этапов.
источник
Vim, 56 байт
Попробуйте онлайн!
Я давно не публиковал сообщения в vim. В основном я использую vim, потому что иногда V - это боль. Поскольку
count
команда, которая идеально подходит для получения числа «1» в строке, будет перезаписывать любые «0» в строке, поэтому мы не можем впоследствии отменить ее.Объяснение:
Это на один байт короче, чем простой способ:
из-за цепочки команд. Так как это разделяет команды, я буду использовать его для объяснения.
Теперь каждый подписанный унарный номер находится на отдельной строке. Используя «11100110001» в качестве примера, на данный момент мы будем иметь:
Так как мы добавляли новые строки в конце каждого матча, перед запуском у нас была пустая строка. После выполнения этого у нас будет '0' (потому что он соответствует серии 0 '1). Поэтому мы просто вызываем,
D
чтобы удалить эту строку, оставив ее пустойисточник
:%s/1+$/
получит вас на один байт короче, если не будет необходимости использовать обратную косую черту+
:(-
вместо0
или-0
Haskell ,
6866 байтПопробуйте онлайн! Вводит в виде списка нулей и единиц. Пример использования:
f [0,0,0,1,1]
доходность[0,-2]
.Объяснение:
Сопоставление с шаблоном в
f(x:r)|(a,b)<-span(>0)r
привязываетx
к первому элементу ввода,a
к (потенциально пустому) списку следующих1
s иb
к остальной части ввода. Учитывая вход[0,1,1,1,0,0,1]
, мы получаемx=0
,a=[1,1,1]
иb=[0,0,1]
.Тогда текущее число является либо суммой
a
отрицания ifx=0
, либо суммойa
плюс один ifx=1
. Это достигается путем индексации сx
в список , содержащий отрицание и приращение функции, и применяя полученную функцию к суммеa
:[(0-),(1+)]!!x$sum a
.Остальной список
b
либо пуст, либо содержит разделительный ноль и следующий номер. Понимание списка[z|_:t<-[b],z<-f t]
пытается соответствоватьb
шаблону_:t
, то есть забыть элемент head и привязать остальную часть списка кt
. Еслиb
пусто, это совпадение не выполняется, и понимание списка оценивается как[]
, что является базовым случаем для рекурсии. В противном случае функцияf
рекурсивно применяется к,t
и понимание списка оценивается для всех элементовz
из результатаf t
.источник
Wolfram Language (Mathematica) , 80 байт
Попробуйте онлайн!
Злоупотребляет механикой
StringCases
, поскольку не проверяет перекрывающиеся шаблоны. Так как мы ищем слева направо, без перекрытий, мы всегда получаем только те числа, которые нам нужны.объяснение
Добавить ноль в конце
Найти все из следующего шаблона ...
Один символ (назовите это
x
), сопровождаемый самой короткой возможной строкой нулевой длины или более длинной (назовите этоy
), сопровождаемый нулем.Применить к соответствующему шаблону: взять длину
y
. Еслиx
ноль, тогда отрицайте значение. Иначе, увеличивай единицу.Это
00
также распространяется, посколькуy
будет пустой строкой, и мы вычислим-0
(== 0
).источник
Brain-Flak , 94 (70?) Байтов
Попробуйте онлайн!
Это на самом деле на удивление лаконично для мозговых штурмов.
Вот комментируемая / читаемая версия:
Если результат может быть обратным, мы можем сделать это для 70 вместо этого:
Этот наконечник шахты является почти идеально подходит для этой ситуации. Но это не совсем работает, так как мы должны нажать 0 перед выполнением операции (считая 1), и операция происходит в цикле. Самое короткое, что я мог придумать, используя этот совет:
что также составляет 94 байта.
источник
Perl 5 , 40 + 1 (
-n
) = 41 байтПопробуйте онлайн!
источник
Шелуха ,
20 18 17 1514 байтПопробуйте онлайн!
объяснение
Расщепление работает следующим образом.
ġ/
разделяет свой аргумент между каждой парой элементов,a,b
для которых/a b
это ложь./a b
это деление с перевернутыми аргументами, поэтомуb
делится наa
. Соответствующие значения в этой программе:/1 1
дает1
(правда)./1 0
дает0
(ложь)./0 1
даетInf
(положительная бесконечность, правдивость)./0 0
даетAny
(специальное NaN-подобное значение, ложь).источник
Точность !! ,
252237 байтИспользует
-0
. Вывод чисел, разделенных символами табуляции, с завершающей табуляцией. Попробуйте онлайн!Время написания фактического алгоритма: 20 минут. Время отладки моего десятичного выходного кода: 45 минут. : ^ P
С комментариями
Я не знаю, объясняют ли эти комментарии код очень хорошо - они основаны на моих заметках для меня, пока я писал его, поэтому они предполагают некоторое понимание того, как Acc !! работает. Если что-то требует большего объяснения, дайте мне знать, и я постараюсь прояснить ситуацию.
источник
Python 2 ,
9692 байтаПопробуйте онлайн!
Thx в ovs и DLosc по 2 байта каждый.
источник
R 119 байт
Попробуйте онлайн!
Код использует это решение из stackoverflow для связанной проблемы (спасибо jeales за идею). Выводом является строка, разделенная пробелом, которая выводится на стандартный вывод.
источник
Желе ,
1918 байтДолжен быть лучший способ ...
Полная программа печати каждого номера с последующим переводом строки.
Попробуйте онлайн!
Как?
источник
QBasic,
8886 байтЭто было весело Многочисленные ревизии, начиная с 107-байтовой версии, привели к одному из самых запутанных кусочков QBasic, который я когда-либо писал. (Редактировать: как ни странно, я смог сыграть в гольф 2 байта, сделав код более понятным.)
Примечание: эта программа читает пользовательский ввод по одному символу за раз, не отображая его на экране (результат использования
INPUT$(1)
вместо обычногоINPUT
выражения). Поэтому, когда вы печатаете, вы не увидите 1 и 0, но десятичные числа будут отображаться по мере их вычисления. Убедитесь, что нажали Enterв конце ввода, чтобы увидеть последний номер и завершить программу.Неуправляемая версия
объяснение
(АКА "Что? Это все еще не имеет смысла!")
Основная стратегия состоит в том, чтобы запустить цикл, который захватывает один символ
INPUT$(1)
каждый раз, делает что-то с ним и продолжает цикл, пока у символа есть значение ASCII больше, чем у!
(то есть, не было новой строки).Мы отслеживаем текущие числа, используя две переменные.
num
количество символов в текущем знаковом унарном числе (включая любой начальный ноль).sign
является1
ли число было ведущим к нулю,0
если нет. Оба они должны быть инициализированы в0
, что отлично подходит для гольфовой версии, потому что числовые переменные в QBasic автоматически инициализируются в0
.Всякий раз, когда мы читаем персонажа, в первую очередь необходимо определить, является ли он
1
или нет0
. Мы будем использовать этот результат дважды, поэтому сохраняем его вisZero
. Технически, это имя вводит в заблуждение, поскольку значение также будет правдивым, если символ является новой строкой. Обратите внимание, что истина в QBasic есть,-1
а фальси есть0
.Теперь, если мы находимся в середине чтения числа (
num > 0
) и достигли нуля или конца ввода (isZero
), нам нужно вычислить, какое число мы закончили читать.sign
магазины0
для позитива,1
для негатива. Чтобы получить1
положительное и-1
отрицательное, нам нужно1-2*sign
.num
хранит правильную величину для позитивов, но на единицу больше, чем величина для негативов (поскольку она включает маркер знака). Таким образом, мы можем использоватьnum-sign
для величины.Умножьте их вместе и напечатайте; затем сбросить
sign
иnum
чтобы0
в ходе подготовки для считывания следующего номера.В противном случае (если мы не достигли нуля или если мы достигли нуля в начале числа), мы обновляем
sign
и выполняемnum
следующие действия:sign
становится,1
если мы смотрим на ведущий ноль; в противном случае, если мы смотрим на одно, оно остается на том, что уже было. Гольф-код -s=s-z
это то же самое:z
есть-1
. Такs
как гарантированно будет0
(потому что это начало нового числа),s-z
будет1
.z
есть0
. Затемs-z
остается в любом значенииs
ранее.num
увеличиваетсяЭто оно!
источник
JavaScript (ES6), 60 байт
Возвращает разделенный пробелами список целых чисел.
Контрольные примеры
Показать фрагмент кода
источник
Луа , 58 байт
Попробуйте онлайн!
Полная программа, принимает данные из командной строки и печатает числа в стандартный вывод, разделенные символами новой строки.
источник