Разверните номер


58

Вы можете вспомнить в первом или втором классе, используя расширенную форму, чтобы узнать о стоимости места чисел. Это проще объяснить на примере, поэтому рассмотрим число 123. В развернутом виде это представляется как 100 + 20 + 3, что помогает молодому уму визуализировать значение места. Это напоминает то, как вы это говорите: сто (плюс) двадцать (плюс) три.

Мы можем расширить это прошлое единиц измерения с десятичными знаками: 2.718 => 2 + 0.7 + 0.01 + 0.008

Ваша задача состоит в том, чтобы написать программу или функцию, которая принимает положительное число с плавающей запятой или ноль (предположим, что оно настолько велико или точно, как ваш язык может его обработать; это не будет в научной нотации) или строку, и печатает / возвращает ее в развернутом виде как объяснено выше.

Вам не нужно ставить пробелы между символами +'s' и 'ноль' до десятичной точки, поэтому приведенный выше пример может быть таким 2+.7+.01+.008. Значения, которые будут равны нулю, должны быть опущены ( 101.01 => 100 + 1 + 0.01), если вход не равен нулю (см. Ниже).

Значения не должны иметь более одного начального нуля до десятичной запятой или любых конечных нулей после нее (no-no's:) 0060, 0000.2, 30., 30.000, .0400. Вход будет соответствовать этому тоже.

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

Контрольные примеры

0 => 0
6 => 6
0.99 => 0.9 + 0.09
24601 => 20000 + 4000 + 600 + 1
6.283 => 6 + 0.2 + 0.08 + 0.003
9000000.0000009 => 9000000 + 0.0000009

22
+1 за «Поскольку у первоклассников короткие интервалы внимания, ваш код должен быть максимально коротким».
Даунгут

2
@ Я рад, что мем все еще работает.
кот

4
Было бы забавно сделать это так же, как мы (французы) считаем, чтобы люди боролись с делом 97 (4 * 20 + 10 + 7) ^^
Katenkyo

2
@ jimmy23013 Да, пока это работает в теории.
NinjaBearMonkey

1
@ Сегодня я не знаю, это всего лишь крайние случаи. Возможно, путь NBZ был бы лучше, но все же, нет, если это действительно было бы интересно
Katenkyo

Ответы:


6

CJam, 33 26 байтов

r_ee\'0fe<f{\~t~}{},'+*0e|

Это не будет работать с интерпретатором Java; это печать плавает по-разному. Попробуйте это с интерпретатором CJam .

Последний тестовый пример печатает 9000000+9e-7, который был признан действительным @NinjaBearMonkey .

Спасибо @ jimmy23013 за удаление 7 байтов!

Как это устроено

r_                           Read a token from STDIN and push a copy.
  ee                         Enumerate its characters, i.e., push the array of all
                             [index character] pairs.
    \                        Swap the original input on top of the stack.
     '0fe<                   Perform vectorized minimum with the character '0'.
                             This replaces all digits with '0', but leaves '.'
                             untouched, since `.' < '0'.
          f{    }            For each [index character] pair, push the pair and the
                             string of zeroes and (possibly) a dot; then:
            \                    Swap the pair on top of the stack.
             ~                   Dump index and character on the stack.
              t                  Replace the string's element at that index with
                                 that character.
               ~                 Evaluate the resulting string.
                 {},         Filter the array to remove zeroes.
                    '+*      Join, using '+' as separator.
                       0e|   If the result is empty, replace it with 0.

Основываясь на той же идее: r_ee\'0fe<f{\~t~}{},'+*0e|.
jimmy23013

@ jimmy23013 Ого, это коротко! Спасибо!
Деннис

5

JavaScript (ES7), 102 байта

n=>+n&&[...n.replace(/^\.0*|\./,"")].map(f=d=>10**p--*d,p=Math.floor(Math.log10(n))).filter(f).join`+`

объяснение

Требуется, чтобы число вводилось в виде строки без начальных нулей (если, конечно, число не является 0 ).

Примечание: из-за странности с плавающей точкой некоторые числа (например .3) получаются неправильными, но теоретически это работает для любого числа.

n=>                             // n = input number as string
  +n&&                          // return 0 if n = 0
  [...n.replace(/^\.0*|\./,"")] // remove leading zeroes after the decimal place
  .map(f=d=>                    // for each digit d in n
      10**p--*d,                // raise the digit to the correct power of 10
    p=Math.floor(Math.log10(n)) // p = power of 10 for the first digit, floor needs to be
  )                             //     used instead of |0 due to negative powers of 10 :(
  .filter(f)                    // remove zeroes, the map function is reused
  .join`+`                      // return the output numbers joined with +

Контрольная работа

Тест использует Math.powвместо **совместимости браузера.


Math.floor=> 0|...?
ETHproductions

@ETHproductions Если входное число меньше, чем 1оно сломалось бы, потому Math.log10(n)что возвращало бы отрицательное число и округляло бы |0к нулю вместо настила.
user81655

Вы можете использовать 0|Math.log10(n),p-=p<0вместо Math.floor(Math.log10(n))?
Дом Гастингс

1
@DomHastings Почти. Он терпит неудачу за n<1потому , что 0|будет делать pравным 0для обоих 0.1и -0.1. Самый короткий путь, который я могу придумать, - p=Math.log10(n),p=p-(p<0)|0это та же длина, что и при использовании Math.floor. :(
user81655

@DomHastings Все равно не сработает n=0.1.
Нил

5

Retina , 86 77 75 байт

Подсчет байтов предполагает, что источник кодируется как ISO 8859-1.

S_`.(?<=(\.\d+))|(?=(\d*)).
Tm`d`0`\..+\B|(?<=^\d).+
¶([.0]+¶)*
+
^0.|\+0$

Конечный перевод строки значителен.

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

объяснение

S_`.(?<=(\.\d+))|(?=(\d*)).

Мы начнем с превращения ввода в отдельный список компонентов перевода строки, хотя верна только начальная (или конечная) цифра. Это делается путем злоупотребления разделенным этапом. Вместо разделения входных данных мы сопоставляем все, поэтому оставшиеся сегменты все пусты. Мы удаляем эти пустые сегменты с помощью _опции. Суть в том, что разделенные этапы также возвращают значения всех групп захвата. Таким образом, мы используем предпросмотр каждого совпадения для захвата правильной части строки: сначала мы пытаемся найти .левую часть совпадения. Если это так, мы фиксируем все с.до и включая цифру, которую мы в настоящее время сопоставляем. В противном случае мы должны быть в целочисленной части ввода, поэтому мы фиксируем все числа после совпадения (включая совпадение). Мы также должны избавиться от самой десятичной точки, поэтому второй захват не является обязательным. Если нет \dнеобходимости захватывать, это просто удалит совпадение из ввода.

Tm`d`0`\..+\B|(?<!=\d).+

Теперь мы используем этап транслитерации, чтобы превратить все нули, кроме начальных / конечных цифр. Мы либо сопоставляем компонент, который меньше 1, с тем, \..+\Bгде \Bмы гарантируем, что мы останавливаем совпадение на одну цифру до конца, либо мы сопоставляем целочисленную часть с тем, (?<=^\d).+где просмотр сзади гарантирует, что мы начинаем одну цифру с числа. Затем на этапе транслитерации любые цифры ( d) заменяются нулями внутри совпадений.

¶([.0]+¶)*
+

Теперь фактический формат вывода должен использовать +не перевод строки в качестве разделителей. Соответствует переводу строки для выполнения этой замены. Пока мы это делаем, мы также удаляем строки, которые содержат только 0s и .s.

^0.|\+0$

Предыдущий этап не удаляет начало или конец 0(потому что те не имеют перевода строки до и после них), поэтому мы удаляем их явно.


4

Python 2, 216 210 196 175 байт

Вот некоторый слегка играемый в гольф код, который я буду играть в гольф, когда у меня будет время. Использует анализ строк.

i=input().split(".")
I=i[0]
e=enumerate
o=[(k+len(I[j+1::])*"0") for j,k in e(I) if k!="0"] 
try:o+=["."+l*"0"+m for l,m in e(i[1]) if m!="0"]
except:0
print "+".join(o or"0")

объяснение

Таким образом, входные данные разделены на целую и десятичную части. Затем, есть понимание списка цикла. В целочисленной части длина строки после десятичного знака умножается на «0», чтобы получить столько нулей в конце этого символа.

Для десятичной части индекс текущего символа - это число нулей перед ним, поэтому эта часть проста.

Попытка и исключение используется, чтобы определить, имеет ли он десятичную часть или нет (с ошибкой).

Конечный результат соединяется со знаком плюс.

Попробуй это здесь!


2
Я думаю, что o if o else ["0"]может быть o or["0"].
lirtosiast

У вас есть пробел в четвертой строке, который добавляет к вашему счету байтов. В четвертой строке вам нужен только один двоеточие. Вы можете удалить пробелы в следующих фрагментах: o=[(...)] for, e(I) if, e(i[1]) if, print "+", и внешняя скобка в o=[(...)а, на самом деле. Наконец, вы можете извлечь последнее условное print"+".join(o)or"0"выражение из функции соединения следующим образом: потому что объединение вернет пустой список, если oоно пустое, поэтому условное вычисление будет выполнено таким же образом, что сэкономит вам один байт.
Огадай

3

Pyth, 30 байт

L.xvbytb|j\+fT.eyXXzjkUT\0kbzz

Тестирование

Основное решение здесь состоит в том, чтобы заменить все цифры на входе 0, затем вставить каждую цифру в нужном месте, вычислить, отфильтровать нули и объединить плюсы. К сожалению, функция eval Пита в настоящее время не принимает лидирующие нули. Я буду работать, чтобы исправить это.

Чтобы обойти эту проблему, я добавил вспомогательную функцию, yкоторая рекурсивно повторяет eval до тех пор, пока не будет выдано никаких ошибок, каждый раз удаляя первую цифру. Обратите внимание, что эта функция будет бесконечно зацикливаться на неверном вводе.

Кроме того, особый случай был необходим для ввода 0.

В целом, я думаю, что код довольно хорош, но языковые возможности могут быть лучше. Кто хочет ошибки?


3

Питон 3, 138

Это в значительной степени основано на подходе TanMath / Ogaday, заключающемся в том, что число читается как строка и обрабатывается таким образом. Я должен использовать звездное присвоение, iчтобы оно правильно обрабатывало целые числа.

j,*i=input().split(".")
e=enumerate
z="0"
print("+".join([(x+len(j[y+1:])*z)for y,x in e(j)if x>z]+["."+o*z+p for o,p in e(i)if p>z]or z))

3

Python, 141 132 128 байт

Этот все еще относительно читабелен. Преобразовать в строку и обрабатывать >1цифры отдельно от <1цифр. У нас также есть особый случай для нуля. Я мог бы убрать еще два пробела ниже, но мне нравится держать их красивыми.

Недостатком является то, что он будет разбит на поплавки с более чем 9 знаками после запятой.

x=str(int(a*1e9))
l=len(x)-10
z="0"
print"+".join([(j+z*(l-i))if l>=i
 else"."+z*(i-l-1)+j
 for i,j in enumerate(x)if j!=z]or z)

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

x=str(int(a*1e9))
l=len(x)-10
z="0"
print "+".join([(j+z*(l-i)) if l>=i
 else ("0."+z*(i-l-1)+j)
 for i,j in enumerate(x) if j!=z]) if a else z

Объяснение:

x=str(int(a*1e9)) # Convert into a string with nine decimals
l=len(x)-10
z="0"
print "+".join([
 (j+z*(l-i)) if l>=i       # Print numbers greater than 1
 else ("0."+z*(i-l-1)+j)   # Print less than one
 for i,j in enumerate(x) if j!=z
]) if a else z             # Special case zero

Вам не нужно включать каждую версию вашего кода; если мы хотим увидеть ваш прогресс в гольф, мы можем посмотреть историю изменений. Кстати, добро пожаловать в PPCG!
lirtosiast

1
Только что обнаружил ... Мне нужно постараться не тратить слишком много времени на этом сайте!
скоростной самолет

2

Mathematica, 81 байт

Inactive@Plus@@(10.^Range[#2-1,#2-Length@#,-1]#/.{0.->Nothing[]})&@@RealDigits@#&

Прецедент:

%[101.01]
(* 100. + 1. + 0.01 *)

3
Я не думаю, что иметь десятичную точку над целыми числами разрешено.
Мартин Эндер

2

CJam, 44 байта

r:TdLT'.-{'0f+IaaI~g*+}fI:dATW%'.##m]f/'+*e&

Попробуй это здесь.

Он не проходит последний тестовый пример и выдает следующее:

9000000+9e-7

Но, скажем, слишком точно, что CJam не может справиться с этим.

объяснение

r:Td
LT'.-         e# Remove the period if any.
{             e# For each character I:
  '0f+        e# Append 0 to each previous string.
  IaaI~g*+    e# Append I as a string if I isn't '0.
}fI
:d            e# Convert each string to float.
ATW%'.##      e# 10 to the kth power where k is the position of the period from the end.
m]            e# Round up, so it becomes 1 if no periods are found.
f/            e# Divide each float by this number.
'+*e&         e# Format and the 0 special case.

2

Python 3, 187 180 173 154 байта

Благодаря удачному предложению @Thomas Kwa, приведенному выше result or['0'], удалось сыграть в гольф на 19 байтов , а также переставить некоторую алгебру ( 154 байта ):

def f(n):
 *m,=n;o='0'
 try:p=m.index('.');m.pop(p)
 except:p=len(m)
 return'+'.join([['.'+o*(i-p)+d,d+o*(p-i-1)][p>i]for i,d in enumerate(m)if d!=o])or o

Моя лучшая попытка на данный момент ( 173 байта ). Основываясь на новом подходе, смотрите основание поста:

def f(n):
 *m,=n;o='0'
 try:p=m.index('.');m.pop(p)
 except:p=len(m)
 return(o,'+'.join([['.'+o*(-1*(p-i))+d,d+o*(p-i-1)][p-i>0]for i,d in enumerate(m)if d!=o]))[eval(n)!=0]

Гольф мой оригинал до 180 байт :

def f(n):x=n.split('.');a,b=(x+[''],x)[len(x)-1];e=enumerate;return('0',"+".join([d+'0'*i for i,d in e(a[::-1])if d!='0'][::-1]+['.'+'0'*i+d for i,d in e(b)if d!='0']))[eval(n)!=0]

Сегодня я изучил новую языковую функцию! Условия через логическое индексирование. Возможно, я немного перестарался.

Я попытался абстрагироваться от понимания, но не смог сделать его короче ( 196 байт ):

e=lambda s:[d+'0'*(len(s)-i-1) for i,d in enumerate(s) if eval(d)]
def f(n):x=n.split('.');a,b=(x+[''],x)[len(x)-1];return['0',"+".join(e(a)+['.'+d[::-1]for d in e(b[::-1])][::-1])][bool(eval(n))]

(Обратные последовательности дороги!)

Пока мой короче, но я думаю, что TanMath может сыграть вничью, чтобы он соответствовал моему: использование e=enumerate, замена passна 0и использование '0'вместо ['0']в выражении return должно сохранить 4 + 3 + 2 = 9 байт! Снижение до 187. Я уверен, что еще несколько байтов можно где-то сбрить ...

редактировать новый подход ( 156 байт ). Тем не менее, он может работать только с точностью до 6 dp, аналогично записи CJam в @ jimmy23013, поэтому он не проходит финальный тест. Я не мог заставить его печатать больше 0, может кто-то другой может. Вместо этого я использовал его в качестве основы для своей лучшей попытки, см. Top (Кроме того, этот подход печатает 0 перед десятичным знаком, но это также кажется действительным). Взял try:... except:...подход от TanMath:

def f(n):
 *m,=n
 try:p=m.index('.');m.pop(p)
 except:p=len(m)
 return('0','+'.join([str(eval(d)*10**(p-i-1))for i,d in enumerate(m)if d!='0']))[eval(n)!=0] 

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

2
Привет @TanMath. Я бы хотел, но у меня недостаточно представителей, чтобы комментировать посты других людей. Как только я получу еще несколько катеров, я обязательно оставлю отзывы в комментариях.
Огадай

2

чистый баш, 210

o= a=${1%.*} b=${1#$a};while [ "$a" ];do c=${a:1};((${a%$c}>0))&&o+=${a%$c}${c//?/0}+;a=$c;done;[ "$b" ]&&{ b=${b#.} a=;while [ "$b" ];do c=${b:0:1};((c>0))&&o+=.$a$c+;b=${b:1};a+=0;done;};o=${o%+};echo ${o:-0}

или же

o= a=${1%.*} b=${1#$a};while [ "$a" ];do c=${a:1};((${a%$c}>0))&&
o+=${a%$c}${c//?/0}+;a=$c;done;[ "$b" ]&&{ b=${b#.} a=;while [ "$b" ]
do c=${b:0:1};((c>0))&&o+=.$a$c+;b=${b:1};a+=0;done;};o=${o%+};echo ${o:-0}

Контрольная работа:

exp() {
    o= a=${1%.*} b=${1#$a};while [ "$a" ];do c=${a:1};((${a%$c}>0))&&
    o+=${a%$c}${c//?/0}+;a=$c;done;[ "$b" ]&&{ b=${b#.} a=;while [ "$b" ]
    do c=${b:0:1};((c>0))&&o+=.$a$c+;b=${b:1};a+=0;done;};o=${o%+};echo ${o:-0}
}
while read num;do
    printf "%-12s => " $num
    exp $num
done <<<$'0\n6\n0.99\n24601\n6.283\n9000000.0000009\n3.1415\n.99'
0            => 0
6            => 6
0.99         => .9+.09
24601        => 20000+4000+600+1
6.283        => 6+.2+.08+.003
9000000.0000009 => 9000000+.0000009
3.1415       => 3+.1+.04+.001+.0005
.99          => .9+.09

2

Python, 131 байт

f=lambda s,k=0,i=0,o="",z="0":s and f(s[1:],(s<z)+k,i+k,o+(s>="1")*([s[0]+~-(s+".").find(".")*z,"."+z*i+s[0]][k]+"+"))or o[:-1]or z

Действительно, очень грязная рекурсивная функция, вероятно, не лучший способ сделать это. Ввод как f("10.0203").


Это даже Python? Любить это.
Огадай

2

C 155 153 161 байт

+2 для ссылки в математической библиотеке (сам источник 159).

main(d,v,p,q)char**v,*p,*q;{for(p=strchr(q=v[1],46),d=p?p-q:strlen(q);*q;++q)*q^46?printf(*q^48|q==v[1]?"%.*f%c":"",d<0?-d:0,(*q-48)*pow(10,--d),q[1]?43:0):0;}

Ungolfed

int main(int d, char **v, char *p, char *q)
{
    for(q = v[1], /* Cache the input string */
        p = strchr(q,'.'), /* find the decimal */
        d = p ? p-q : strlen(q); /* calculate number of digits before decimal */
        *q; /* loop while still input data */
        ++q) /* iterate to next character */
    {
        *q^46 /* if not at the decimal point... */
            ? printf(*q^48 || q == v[1] /* if not a zero, or if the string itself is zero... */
                ? "%.f%c" /* print the digit */
                : "", /* else print nothing */
                d<0 ? -d : 0, /* Calculate number of places after decimal to print */
                (*q-48)*pow(10,--d), /* Calculate the digit at the desired power of 10 */
                q[1]?43:0) /* If the next character is still valid input, print the '+' */
            : 0 /* else, do nothing */
    }
}

2

Дьялог АПЛ , 47 байт

{×⍎⍵:1↓∊'+',¨0~⍨(⍎¨w)×10*(⍵⍳'.')-1+⍳≢w←⍵~'.'⋄0} 

Принимает число в символьной векторной форме, например '123'.

Примеры:

      f←{×⍎⍵:1↓∊'+',¨0~⍨(⍎¨w)×10*(⍵⍳'.')-1+⍳≢w←⍵~'.'⋄0} 
      ↑⍕¨f¨,¨'0' '6' '0.99' '24601' '6.283' '900000.000009'
0                     
6                     
0.9 + 0.09            
20000 + 4000 + 600 + 1
6 + 0.2 + 0.08 + 0.003
900000 + 0.000009     

Примечания:
○ Причиной изменения последнего примера является то, что APL, как и некоторые другие представления, по умолчанию переключается на научную запись для таких крайних чисел.
○ Фраза ↑⍕¨f¨,¨нужна только для одновременной обработки всех примеров.



1

perl, 132 байта

131 +1 за -pпереключатель.

Это основано на моем предыдущем sedответе :

1while s/^([1-9]\d*)([1-9])(0*)([+.].*|)$/${1}0$3+$2$3$4/||s/([1-9]0*)\.([0-9])/$1+.$2/||s/\.(0*)([1-9])(\d*[1-9])$/.$1$2+.${1}0$3/

Тестирование:

perl -pe'1while s/^([1-9]\d*)([1-9])(0*)([+.].*|)$/${1}0$3+$2$3$4/||
    s/([1-9]0*)\.([0-9])/$1+.$2/||s/\.(0*)([1-9])(\d*[1-9])$/.$1$2+.${1}0$3/
' <<<$'0\n6\n0.99\n24601\n6.283\n9000000.0000009\n3.1415'
0
6
0.9+.09
20000+4000+600+1
6+.2+.08+.003
9000000+.0000009
3+.1+.04+.001+.0005

1

Powershell - 172 166 193 байта

Все в одной строке:

$z=([string]$args[0])-split"\.";$y=$z[0].length-1+0.6;($z|%{$x=[char[]]$_;if($y-gt0){($x|%{$_+"0"*(-1+$y--)})}else{($x|%{"0."+"0"*[math]::abs($y--)+$_})}}|?{-not($_-match'^[0.]+$')})-join' + '

Ungolfed:

$z=([string]$args[0]) -split "\."
$y=$z[0].length-1+0.6
($z | %{
    $x=[char[]]$_
    if($y -gt 0) {
        ($x | %{$_+"0"*(-1+$y--)})
    } else {
        ($x | %{"0."+"0"*[math]::abs($y--)+$_})
    }
} | ?{ -not($_ -match '^[0.]+$')}) -join ' + '

Контрольные примеры плюс один дополнительный:

PS> (0, 6, 0.99, 24601, 6.283, 9000000.0000009, [math]::pi) | %{.\expand.ps1 $_}

6
0.9 + 0.09
20000 + 4000 + 600 + 1
6 + 0.2 + 0.08 + 0.003
9000000 + 0.0000009
3 + 0.1 + 0.04 + 0.001 + 0.0005 + 0.00009 + 0.000002 + 0.0000006 + 0.00000005 + 0.000000003 + 0.0000000005 + 0.00 000000008 + 0.000000000009 + 0.0000000000007 + 0.00000000000009    
PS>

Ваше регулярное выражение отфильтровывает $args = 0. Вот простое исправление ошибки, которое также экономит 3 байта
Веска


1

Perl, 248 байт

Фу, я нобист в Perl, играю в гольф.

@a=split/\./,<>;
@b=split``,$a[1];
@c=split``,$a[0];
for($i=0;$i<length$a[0];$i++){
   $_.=($c[$i]!=0)?$c[$i]."0"x((length$a[0])-$i-2)."+":"";
}
for($i=1;$i<=length$a[1];$i++){
   $_.=($b[$i-1]!=0)?"0."."0"x($i-1).$b[$i-1]."+":"";
}
chop;
($_=="")?print"0 ":print;

Попробуй это здесь.


Кажется, это не работает с целыми числами.
Ф. Хаури

Я поставил неправильную ссылку Ideone. Он не учитывает изменения, сделанные в режиме редактирования. :( Это должно работать сейчас.
Пол Пикард

У вас где-то ошибка: когда я вхожу, 5возвращаюсь 50.
Ф. Хаури

Странно, так как я проверил 5 по ссылке, которую я предоставил вчера после того, как вы оставили свой первый комментарий. Не возражаешь сейчас? (Я снова изменил ссылку)
Пол Пикард

Я только что проверил ваш скрипт на моем Perl-интерпретаторе (v5.20.2)
F. Hauri

1

Ява, 284 244 243 байта

String x(String s){int b=s.length(),d=(d=s.indexOf(46))<0?b:d,i=-1,k=0;String o="";for(char c;++i<b;)o+=(c=s.charAt(i))>48?(k++>0?" + ":"")+(d-i>0?c:"0.")+new String(new char[Math.abs(d-i)-1]).replace('\0','0')+(d-i>0?"":c):"";return b<2?s:o;}

К сожалению, я не смог найти более короткий способ создания повторяющихся строк, чем:

  • построить char[]нужной длины
  • использовать Arrays.fillдля установки символов
  • использовать, new Stringчтобы его можно было объединить

С вдохновением @Khaled A Khunaifer я смог сбрить 40 байт.

Редактировать: indexOfпринимает int, чтобы я мог заменить '.'на 46. К сожалению, это не представляется возможным с replace.


Мне удалось сократить его до 250, проверьте ideone.com/HqLnMo
Khaled.K

@Khaled A Khunaifer Кажется, в вашем решении проблемы с однозначными контрольными случаями. Но мне нравится ваш способ генерирования нулей.
ECS

исправить эту .replace('\0','0')функцию заменить Stringне ожидайте char, это должно быть.replace("\0","0")
Khaled.K

@ Khaled A Khunaifer Это работает в моих тестовых случаях, также docs.oracle.com/javase/8/docs/api/java/lang/…
ECS

1

Python, 125 байт

После удаления моего первого ответа (sry!), Который не мог обработать небольшие числа из-за проблем с эпсилоном, я нашел другое решение. Он обрабатывает числа с плавающей запятой, а также целые числа, завершающие нули (!) И записывается как функция.

Спасибо @ogaday за полезные советы и компактное исправление 0!

Golfed:

def f(x):x+='.';i=x.find('.');z=list(x);del z[i];return'+'.join([str(int(o)*10**(i-j-1))for j,o in enumerate(z)if'0'<o])or'0'

Ungolfed:

def f(x):
  x+='.'
  i=x.find('.')
  z=list(x)
  del z[i]   
  return '+'.join([str(int(o)*10**(i-j-1)) for j,o in enumerate(z) if '0'<o]) or '0'

Использование:

>>> f("0")
'0'

>>> f("32.005")
'30+2+0.005'

>>> f("100020003000009000000.0007")
'100000000000000000000+20000000000000000+3000000000000+9000000+0.0007'

>>> f("1000000000009000000.0007000000000000000002")
'1000000000000000000+9000000+0.0007+2e-22'

>>> f("0001.99")
'1+0.9+0.09'

1
Приятно. Однако f('0')тест не проходит , и когда я копирую и вставляю текст прямо в мой интерпретатор, я получаю научную запись (что, я думаю, хорошо). Также list(c)короче. Если вы объединяете '.'перед тем, как превратить его в список, добавлять его []тоже не нужно . Использование findвместо индекса в строке перед превращением ее в список, после добавления '.'также экономит вам байт. Изменение порядка неравенства также позволяет убрать дополнительное пространство:def f(x):x+='.';i=x.find('.');z=list(x);del z[i];return"+".join([str(int(o)*10**(i-j-1))for j,o in enumerate(z)if"0"<o])or'0'
Ogaday

1

CoffeeScript, 144 байта

Прямое решение:

X=(n)->[m,k]="#{n}".split '.';(c+Array(m.length-i).join 0for i,c of m when+c).concat(".#{Array(++i).join 0}"+c for i,c of k when+c).join('+')||0

Исполняемые:


1

Stax , 18 байт

ºî≤FlφLfÜG→\ΦUq╜♥←

Запустите и отладьте его

Распакованный, размазанный и прокомментированный, это выглядит так.

c           copy input
!C          terminate if input is falsy
y{          for each character in the string input...
  y.\d'0R   replace each digit in the input with "0"
  ia&       then replace the nth character back to its original value
  e         eval as float
m           map using block to produce array
{f          filter out zeroes
'+*         join with "+"

Запустите этот

Как и многие другие опубликованные решения, он производит 9000000+9e-7для последнего теста. Согласно установленному прецеденту это разрешено, потому что контрольный пример слишком точен для языка.


0

Луа, 350 байт

Я думаю, что есть еще два способа сделать это:

  • Я мог бы использовать macro.defineдля замены некоторых выражений обыкновенных (не могу проверить прямо сейчас, и не уверен, что это заставит меня получить несколько байтов)

  • Используйте разделение на точке вместо итерации по всей строке. Еще раз, я не уверен, что это уменьшит размер этой функции, так как манипулирование строкой в ​​lua довольно болезненно.

function f(s)v,r=s:find("%.")or#s+1,""if #s==1 then return s end for i=1,#s do a=""(v>i and s:sub(i,v-1)or s:sub(v,i)):gsub(".",function(c)a=a..(not a:find(c)and(c==s:sub(i,i)or c==".")and c or 0)end)s,r=v<i and s:sub(0,i-1).."0"..s:sub(i+1,#s)or s,r..((#a==a:find("%.")or tonumber(a)==0)and""or a:gsub("%.","0.")..(i~=#s and"+"or""))end return r end

Пояснения

function f(s)
  v=s:find("%.")or #s+1               -- v=index of the dot in a decimal number
  r=""                                -- v=#s+1 when s is an integer(v=0 would screw sub())
  if #s==1 then return s end          -- exit if s is a single digit
  for i=1,#s                          -- iterate over s
  do
    a=""

    (v>i and s:sub(i,v-1)or s:sub(v,i)-- only send the integer OR decimal part to gsub
      ):gsub(".",function(c)          -- iterate over each character of s:sub()

    -- a contains the next number to be concatenated to the string r(the one to be returned)
      a=a..(not a:find(c)             -- we concatenate a with c if a doen't contains
        and(c==s:sub(i,i)or c==".")   -- c, and c is either a dot, or the next number
             and c or 0)              -- to be add, we put a 0 otherwise
    end)
    -- we concatenate the new a with the string already formed
    r=r..((#a==a:find("%.")           -- if a=="." or a's value is 0
            or tonumber(a)==0)and""   -- we concatenate an empty string
      or a:gsub("%.","0.")            -- else, we replace the (possible) leading dot by "0."
      ..(i~=#s and"+"or""))           -- and concatenate a "+" if it isn't the last number to be added

    s=v<i and s:sub(0,i-1)            -- We then replace the digit we have worked with
      .."0"..s:sub(i+1,#s)or s        -- to prevent duplicates
  end
  return r
end

Вы можете протестировать lua онлайн и использовать следующий исходный код, чтобы запустить его с некоторыми тестами.

function f(s)v,r=s:find("%.")or#s+1,""if #s==1 then return s end for i=1,#s do a=""(v>i and s:sub(i,v-1)or s:sub(v,i)):gsub(".",function(c)a=a..(not a:find(c)and(c==s:sub(i,i)or c==".")and c or 0)end)s,r=v<i and s:sub(0,i-1).."0"..s:sub(i+1,#s)or s,r..((#a==a:find("%.")or tonumber(a)==0)and""or a:gsub("%.","0.")..(i~=#s and"+"or""))end return r end

print(f("3123.12333"))
print(f("9545"))
print(f("9000000.0000009"))
print(f("6"))

0

C 253 байта

m(char*i){int k,j=0,s=0,d=0;while(i[s])s++;while(i[d]!=46)d++;while(j<d){if(i[j]!=48){for(k=0;k<(d-j);k++)putchar(k?48:i[j]);putchar(43);}j++;}while(++j<s)if(i[j]!=48){putchar(46);for(k=0;k<(j-d);k++)putchar(k==(j-d-1)?i[j]:48);putchar(43);}putchar(8);}

Примечание: putchar(8)должен выполнять возврат.

 Input: 1230.0456
Output: 1000+200+30+.04+.005+.0006

Подробно , попробуйте здесь

while(i[s]) s++;
while(i[d]!=46) d++;

while (j<d)
{
    if (i[j]!='0')
    {
        for(k=0;k<(d-j);k++) putchar(k? '0': i[j]);
        putchar(43);
    }
    j++;
}

while (++j<s)
if (i[j]!='0')
{
    putchar(46);
    for(k=0; k<(j-d); k++) putchar(k==(j-d-1)? i[j]: '0');
    putchar(43);
}

putchar(8);

0

sed, 136 128 байт

Уменьшается на 8 символов за счет удаления пробелов и бесполезно 0.

:;s/^([1-9][0-9]*)([1-9])(0*)([+.].*|)$/\10\3+\2\3\4/;s/([1-9]0*)\.([0-9])/\1+.\2/;s/\.(0*)([1-9])([0-9]*[1-9])$/.\1\2+.\10\3/;t

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

sed -r ':;
    s/^([1-9][0-9]*)([1-9])(0*)([+.].*|)$/\10\3+\2\3\4/;
    s/([1-9]0*)\.([0-9])/\1+.\2/;
    s/\.(0*)([1-9])([0-9]*[1-9])$/.\1\2+.\10\3/;
    t' <<<$'0\n6\n0.99\n24601\n6.283\n9000000.0000009\n3.1415'
0
6
0.9+.09
20000+4000+600+1
6+.2+.08+.003
9000000+.0000009
3+.1+.04+.001+.0005

0

JavaScript (ES7), 114 байт

s=>(p=s.search(/.\b/),i=-1,[for(c of s)if((i++,c>0))(z=s.substring(i,p).replace(/d/g,0),i<p?c+z:z+c)].join`+`||s

Работает с произвольными числами длины, потому что он использует строковые манипуляции повсюду.

Без понимания массива (122 байта):

s=>[...s].map((c,i)=>c<'1'?'':(z=s.substring(i,p).replace(/\d/g,0),i<p?c+z:z+c),p=s.search(/.\b/)).filter(x=>x).join`+`||s

Ungolfed:

function expand(s) {
    zeros = s.replace(/\d/g, "0");
    point = s.indexOf(".");
    if (point < 0) point = s.length;
    result = [];
    for (i = 0; i < s.length; i++) {
        if (s[i] > "0") {
            if (i < point) result.push(s[i] + zeros.slice(i, point - 1));
            else result.push(zeros.slice(point - 1, i) + s[i]);
         }
     }
     return result.length ? result.join("+") : s;
}

Насколько я знаю, этот новый синтаксис понимания массива
взят

@manatwork Спасибо, я обновил его, когда добавлял версию без гольфа.
Нил

0

R - 133 байта

Надежный, игнорирует Machine Epsilon и работает также с конечными нулями.

а) Гольф:

f=function(x)if(x=='0')x else{z=strsplit(x,'')[[1]];i=which(z=='.');n=as.numeric(z[-i])*10^(i-seq(z)[-1]);paste(n[n>0],collapse='+')}

Ungolfed:

f=function(x)
  if(x=='0') 
    x 
  else {
    z=strsplit(x,'')[[1]]
    i=which(z=='.')   
    n=as.numeric(z[-i])*10^(i-seq(z)[-1])  
    paste(n[n>0],collapse='+')
  }

Использование:

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