Ефективний підрахунок


35

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

один два три чотири п'ять шість сім вісім дев'ять десять;
одинадцять, дванадцять, тринадцять, чотирнадцять, п’ятнадцять, шістнадцять, сімнадцять, вісімнадцять, дев’ятнадцять, двадцять;
двадцять один, двадцять два, двадцять три, двадцять чотири, двадцять п’ять ...

Врешті-решт я втомився вимовляти кожне з цих багатоскладових чисел. Маючи математичну думку, я створив набагато ефективніший метод підрахунку:

один два три чотири п'ять шість сім вісім дев'ять десять;
один, два, три, чотири, п’ять, шість, сім, вісім, дев’ять, двадцять;
один, два, три, чотири, п’ять, шість, сім, вісім, дев'ять, тридцять ...

Як бачите, я б лише вимовив цифру (і), які змінилися від попереднього числа. Це має додаткову перевагу в тому, що він значно повторюється, ніж англійські імена для чисел, а тому вимагає меншої кількості сил для обчислення.

Виклик

Напишіть програму / функцію, яка приймає натуральне ціле число та виводить / повертає так, як я би порахував це: тобто найправіший ненульовий розряд і всі проміжні нулі.

Приклади

   1    1
   2    2
  10   10
  11    1
  29    9
  30   30
  99    9
 100  100
 119    9
 120   20
 200  200
 409    9
1020   20

Повний список тестових випадків не повинен бути необхідним. Це A274206 на OEIS.

Правила

  • Ваш запис теоретично повинен працювати для всіх натуральних чисел, ігноруючи точність та проблеми з пам’яттю.
  • Введення та вихід повинні бути десятковими.
  • Ви можете прийняти введення та / або вихід як число, рядок або масив цифр.
  • Введення гарантується як натуральне число. Ваш запис може зробити що завгодно для недійсного введення.

Це , тому найкоротший код у байтах виграє.


Так чи містить "у десятковій формі" список десяткових цифр, наприклад [1,0,2,0]-> [2,0]для останнього тестового випадку? (Мені незрозуміло щодо фрази "однопозиційний масив").
Джонатан Аллан

1
@JonathanAllan Під масивом "один елемент" я мав на увазі масив, який містить одне число або рядок, який представляє ціле число. Я не вважав, що дозволити масиви цифр було гарною ідеєю, але зараз це виглядає як довільне обмеження, оскільки рядки дозволені (а рядки дуже схожі на масиви на багатьох мовах). Тому я дозволю масив цифр, якщо немає вагомих причин цього не робити.
ETHproductions

5
Пограбувавши, ви вкрали мій секрет: P
LegionMammal978

1
Я думаю, що майже кожен розраховував так, як дитину. ;) Принаймні я так і зробив. :)
Кевін Круїссен

7
@KevinCruijssen "як дитина"?
Мартін Ендер

Відповіді:


19

Python 2 , 28 байт

f=lambda n:n%10or 10*f(n/10)

Спробуйте в Інтернеті!

Рекурсивна формула працює дуже чисто. Якщо остання цифра не є нульовою, виведіть її. В іншому випадку видаліть кінцевий нуль, обчисліть вихід для цього і помножте його на 10.


11

Желе , 6 3 байти

-3 байти, маючи введення-вивід як десятковий список цифр .

ṫTṪ

Тестовий набір у Спробуйте онлайн!

Як?

ṫTṪ - Main link: listOfDigits  e.g.  [1,    0,    2,    0]  or [1,      1,    9  ]
 T  - truthy indexes                 [1,          3      ]     [1,      2,    3  ]
ṫ   - tail (vectorises)              [[1,0,2,0],  [2,0]  ]     [[1,1,9],[1,9],[9]]
  Ṫ - tail pop                                    [2,0]                       [9]

Якщо ми не змогли взяти десяткові списки, то 6 байт:

DµṫTṪḌ

Що ви можете побачити тут .

Це робить те саме, але попередньо перетворює ціле число в десятковий список і згодом перетворює назад на ціле число.


Коли я прокручував перші кілька відповідей, я сказав собі: "Маю на увазі, що є 3-
байтне

9

C, 30 29 27 байт

Гордий цим, коли я зловживаю двома подвигами С, щоб розіграти це (описано в кінці посту); Це спеціально для C (GCC)


3) b=10;f(a){a=a%b?:b*f(a/b);}// 27 байт

2) b;f(a){b=a=a%10?:10*f(a/10);}// 29 байт

1) f(i){return i%10?:10*f(i/10);}// 30 байт

Спробуйте в Інтернеті (27-байтна версія)


Перша спроба (30 байт): Зловживає тим фактом, що в GCC, якщо в терміналі не оголошено значення, умовне значення повернеться. Отже, чому мій потрійний оператор порожній для значення повернення істини.

Друга спроба (29 байт): Зловживає помилкою пам’яті в GCC, де, наскільки я розумію, якщо функція не має значення, що повертається, коли більш ніж дві змінні були змістовно використані у функції, останнє встановлене значення першої змінної аргументу буде повернуто.
   (Редагувати: але це "задане значення" повинно встановлюватися певними способами, наприклад, встановити змінну =або +=працює, але встановити її %=не працює; дивно)

Третя спроба (27 байт): Оскільки я маю на меті доцільно використовувати другу змінну (б) у будь-якому разі, щоб належним чином зловживати помилкою пам'яті, згаданою вище, я можу також використовувати її як фактичну змінну для "10" для заміни.
   (Примітка: я повинен бути в змозі свопу a=a%bз , a%=bщоб зберегти інші байти , але , до жаль , це призводить до того , помилку пам'яті експлуатує вище зупинки «працює», так що я не можу)


Ви можете додати "GCC" до заголовка вашої відповіді, оскільки це специфічно для GCC (він не працює на ляскання). Крім того, "помилка пам'яті", ймовірно, є лише невизначеною поведінкою, яка, як правило, працює через специфічний макет кадру стека, який використовує GCC. Можливо, це не працює на інших платформах, навіть із GCC.
симон

@gurka Готово, дякую
Альберт Реншо

7

Сітківка , 7 6 байт

!`.0*$

Спробуйте в Інтернеті (усі тестові випадки)

Виведення збігів цифри з будь-якими нулями в кінці вхідного рядка. Хоча це і не потрібно, це також трапляється працювати 0.


Так, я вважав, що [1-9](або [^0]) це буде потрібно замість цього \d. Я здогадуюсь, що жадібність *кожного разу забезпечує правильний вихід.
ETHproductions

@ETHproductions Це не має нічого спільного з жадібністю, *а з тим, що матчі шукають зліва направо. \d0*?$також працював би.
Мартін Ендер

за допомогою регулярного .0*$
виразу

Якщо є (досить короткий) спосіб вивести лише останній матч, ви можете використовувати.0*
12Me21

@ 12Me21 Єдиний спосіб зробити це - лише узгоджувати останній випадок, або використовувати заміну чи щось. Це не буде коротше.
mbomb007

7

Cubix , 18 32 байти

Я думаю, що мені доведеться витратити десь на це пізніше і подивитися, чи зможу я його трохи стиснути. Але на даний момент ось воно.
Виявляється, я думав про це зовсім неправильно. Тепер процес поступово застосовує мод (1,10,100,1000, ...) до цілого входу і виводить перший, який не дорівнює нулю. Трохи нудніше, але коротше.

!N%*I1^\.u;u@O\;;r

Спробуйте тут

    ! N
    % *
I 1 ^ \ . u ; u
@ O \ ; ; r . .
    . .
    . .

Завжди приємно бачити відповідь Cubix :)
Олівер

@obarakon Отримав вдосконалену програму. Дійсно зробив це не так
MickyT


5

Javascript 19 18 байт

Завдяки ETHproductions за те, що ви граєте на один байт, а Patrick Roberts - за два байти

x=>x.match`.0*$`

Повертає масив рядків, який відповідає регексу буття в кінці вхідного рядка з будь-яким символом з подальшим найбільшою можливою кількістю нулів.

Спробуйте в Інтернеті


5
Я не думаю, що вам це потрібно g, так як тут знайдеться лише одна відповідність.
ETHproductions

Збережіть 2 байти, скориставшисьx=>x.match`.0*$`
Патрік Робертс



3

Брахілог , 2 байти

a₁

Спробуйте в Інтернеті!

Суфікс вбудований a₁для цілих чисел реалізується як:

brachylog_adfix('integer':1, 'integer':0, 'integer':0).
brachylog_adfix('integer':1, 'integer':I, 'integer':P) :-
    H #\= 0,
    H2 #\= 0,
    abs(P) #=< abs(I),
    integer_value('integer':Sign:[H|T], I),
    integer_value('integer':Sign:[H2|T2], P),
    brachylog_adfix('integer':1, [H|T], [H2|T2]).

Брахілог любить мати можливість ставитися до цілих чисел як до списків цифр, і для цього використовує спеціальний присудок integer_value/2. Цікавим integer_value/2тут є те, що оскільки він повинен вміти правильно переводити список знаків з провідними нулями, він в кінцевому підсумку також зможе перевести ціле число до списку знаків з провідними нулями, тому предикати, які не хочуть, щоб це трапляються (більшість із них, особливо таких, що не мають нондетів a) забороняють заголовкам їхніх цифрових списків бути 0. Так, хоча a₁генерує суфікси найкоротші для списків та рядків, він пропускає будь-який суфікс цілого числа з провідним 0, який у крім видалення дублікатів, також означає, що перший генерований суфікс - це найправіша ненульова цифра з усіма кінцевими нулями.


2

Мозок-Флак , 74 байти

{({}<>)<>}(()){{}<>(({}<>)[((((()()()){}){}){}){}]<(())>){((<{}{}>))}{}}{}

Спробуйте в Інтернеті!

Друкує лише останні не 0 і всі кінцеві 0.

Пояснення:

{({}<>)<>}                    # Move everything to the other stack (reverse the input)
(())                          # Push a 1 to get started
{                             # do...
  {}<>                        #   pop the result of the equals check (or initial 1)
  (                           #   push...
    ({}<>)                    #     the top value from the other stack (also put this on the stack)
    [((((()()()){}){}){}){}]  #     minus the ASCII value of 0
    <(())>                    #     on top of a 1
  )                           #   close the push   
  {                           #   if not zero (ie. if not equal)
    ((<{}{}>))                #     replace the 1 from 3 lines back with a 0
  }{}                         #   end if and pop the extra 0
}                             # while the copied value != "0"
{}                            # pop the result of the equals check



2

R, 33 байти

Реалізується як неназвана функція

function(x)rle(x%%10^(0:99))$v[2]

Це стосується моди від 10 ^ 0 до 10 ^ 99. rleвикористовується для зниження результатів, щоб другий елемент завжди був результатом, який ми бажаємо.
Спробуйте в Інтернеті!


2

Зш , 18 16 байт

<<<${(M)1%[^0]*}

Спробуйте в Інтернеті! Спробуйте в Інтернеті!

Баш , 25 байт

r=${1%[^0]*}
echo ${1#$r}

Спробуйте в Інтернеті!


Оболонки повинні викликати зовнішні програми, щоб використовувати регулярний вираз, тому ми маємо робити з глобалізацією.

${1%[^0]*}Розширення відповідає найкоротшому суффиксу , що починається з ненульовим символом, і видаляє його.

  • У Zsh додавання (M)прапора спричиняє збереження відповідного суфікса замість видалення.
  • У Bash ${1% }розширення видаляє як префікс все, що залишилося.

1

GNU sed , 17 14 + 1 (r прапор) = 15 байт

Редагувати: на 2 байти менше завдяки Райлі

s:.*([^0]):\1:

Він працює, видаляючи все до найнебезпечнішої цифри, яка потім друкується разом із будь-якими існуючими нульовими нулями. Сценарій може обробляти кілька тестів за один запуск, кожен в окремому рядку.

Спробуйте в Інтернеті! (усі приклади тесту)


1

Математика, 26 байт

Чиста функція, яка приймає список цифр і виводить список цифр:

#/.{___,x_,y:0...}:>{x,y}&

Пояснення

#                           First argument
 /.                           Replace
   {                              start of list followed by
    ___,                          zero or more elements followed by
        x_,                       an element (referred to later as x) followed by
           y:0...                 a sequence of zero or more 0s (referred to later as y) followed by
                 }                end of list
                  :>            with
                    {x,y}         {x,y}
                         &   End of function.

Це працює, оскільки він знаходить крайній лівий збіг для x, який повинен бути самим правильним ненульовим елементом списку, оскільки за ним слідує послідовність нулів більше 0s, а потім кінець списку.


1

Java 8, 47 байт

це лямбда-вираз, присвоєний IntUnaryOperator:

x->{int m=1;for(;x%m<1;m*=10);return x%m*m/10;}

пояснення: помножити m на 10, поки x%mне стане 0. return x%m*m/10вимагає ділення, оскільки m на порядок більше, ніж бажаний результат.


1

Perl 6 , 10 байт

{+m/.0*$/}

Тривіальний розчин регексу. Вводить і виводить число.


1

MATL , 10 7 байт

3 байти збережено завдяки @B. Мехта!

tfX>Jh)

Введення та вихід - це масив цифр.

Спробуйте в Інтернеті!

Або перевірити всі тестові випадки .

Пояснення

t     % Input string implicitly. Duplicate
f     % Push indices of non-zero digits
X>    % Keep maximum, say k
Jh    % Attach 1j to give [k, 1j]. This is interpreted as an index "k:end"
)     % Index into original string. Display implcitly

Оскільки нам дозволяється приймати вхід і вихід як вектор цілих чисел, ви можете вилучити 48-цілком, заощадивши 3 байти: Спробуйте це в Інтернеті!
Б. Мехта

1

C #, 30 28 байт

Виходячи з цієї відповіді на JavaScript , тому я гадаю, що всі кредити йому належать.

Гольф

i=a=>a%10<1?10*i(a/10):a%10;
  • -2 байт, видаливши ()навколо aзавдяки Emigna

1
Я думаю, вам потрібно чітко назвати функцію, iщоб це працювало, коли ви використовуєте рекурсію.
Емінья

@Emigna ви праві! Я цілком пропустив це :(
Metoniem

Оновлено його, але я не впевнений на 100%, чи правильно це
Metoniem

1
Я не знаю консенсусу щодо цього в C #. Цей синтаксис є дійсним, але працює, лише якщо делегат уже оголошений (інакше iбуде недекларовано для рекурсивного виклику).
Емінья

1
Дужки навколо aне потрібні в жодному разі.
Емінья

1

J, 27 байт

10&|`(10*(p%&10))@.(0=10&|)

Він заснований на формулі xnor, тому кредити йому.


1

Котлін, 49 байт

лямбда, віднесена до (List<Int>) -> List<Int>

{a->a.slice(a.indexOfLast{it in 1..9}..a.size-1)}
  • неявна назва параметра itвindexOfLast
  • .. для будівництва діапазонів


1

05AB1E , 9 байт

RD0Ê1k>£R

Спробуйте в Інтернеті! або як тестовий набір

Пояснення

R          # reverse input
 D         # duplicate
  0Ê       # check each for inequality with 0
    1k     # get the index of the first 1
      >    # increment
       £   # take that many digits from the input
        R  # reverse



@MagicOctopusUrn: Це лише перевірка останньої цифри. Це має бути остання ненульова цифра і все після.
Емінья



1

05AB1E , 4 байти

ĀÅ¡θ

I / O як перелік цифр.

Спробуйте в Інтернеті або перевірте всі тестові справи (тестовий набір містить з'єднання для кращої читабельності).

Пояснення:

Ā     # Python-style truthify each digit in the (implicit) input-list (0 if 0; 1 if [1-9])
      #  i.e. [9,0,4,0,3,0,0] → [1,0,1,0,1,0,0]
 Å¡   # Split the (implicit) input-list on truthy values (1s)
      #  i.e. [9,0,4,0,3,0,0] and [1,0,1,0,1,0,0] → [[],[9,0],[4,0],[3,0,0]]
   θ  # And only leave the last inner list
      #  i.e. [[],[9,0],[4,0],[3,0,0]] → [3,0,0]
      # (after which it is output implicitly as result)


0

Haskell 57 байт

f(x:s)a|x=='0'=f s$'0':a|1>0=x:a
t x=f(reverse.show$x)[]

Input    -> Output
t 120    -> "20"
t 30200  -> "200"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.