Уменьшить число на наибольшую цифру


33

Задача:

Учитывая целое число в десятичной системе счисления, уменьшите его до одной десятичной цифры следующим образом:

  1. Преобразуйте число в список десятичных цифр.
  2. Найти самую большую цифру, D
  3. Удалить D из списка. Если D встречается несколько раз, выберите первое слева (в наиболее значимой позиции), все остальные должны остаться нетронутыми.
  4. Преобразовать полученный список в десятичное число и умножить его на D.
  5. Если число больше 9 (имеет более 1 десятичной цифры), повторите всю процедуру, вводя в нее результат. Остановитесь, когда вы получите однозначный результат.
  6. Показать результат.

Пример:

26364 -> 
1. 2 6 3 6 4 
2. The largest digit is 6, so D=6
3. There are two occurrences or 6: at positions 1 and 3 (0-based). We remove the left one,
    at position 1 and get the list 2 3 6 4 
4. we convert the list 2 3 6 4 to 2364 and multiply it by D:
   2364 * 6 = 14184
5. 14184 is greater than 9 so we repeat the procedure, feeding 14184 into it.

Мы продолжаем, повторяя процедуру для 14184 и так далее, и мы проходим следующие промежуточные результаты, в конечном итоге достигая 8:

11312
3336
1998
1782
1376
952
468
368
288
224
88
64
24
8

Таким образом, результат для 26364 - 8.

Входные данные: целое число / строка, представляющая целое число

Выход: одна цифра, результат сокращения, примененный к числу.

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

9 -> 9
27 -> 4
757 -> 5
1234 -> 8
26364 -> 8
432969 -> 0
1234584 -> 8
91273716 -> 6

Это , поэтому выигрывают самые короткие ответы в байтах на каждом языке.


3
Что это, если число больше 10 или имеет более 1 десятичного знака . Число 10 имеет более 1 десятичной цифры, но не больше десяти.
Адам

@ Adám Зачем кодировать логику 10 -> 10?
Ян Х.

1
@ Adám Вы правы, мне следовало написать «больше 9». Я собираюсь редактировать описание. Благодарность!
Гален Иванов

Кто-нибудь исследовал гистограмму этой функции для достаточно больших регионов? Кажется, у него много нулей; Я также получил много восьмерок при составлении тестовых случаев.
Гален Иванов

2
Кроме того, случайное число, делимое на 4, имеет 3/5 вероятность того, что произведение двух последних цифр будет делиться на 8.
Орджан Йохансен,

Ответы:



11

JavaScript (ES6), 49 байт

f=n=>n>9?f(""+n.replace(m=Math.max(...n),"")*m):n

Принимает ввод как строковое представление целого числа, например f("26364").

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



6

Pyth , 16 байт

.WtH`*s.-ZKeSZsK

Принимает ввод в виде строки. Попробуй это здесь! (Альтернатива: .WtH`*s.-ZeSZseS)

Pyth , 18 байт

.WgHT*s.-`ZKeS`ZsK

Принимает ввод как целое число. Попробуй это здесь!

Как это работает

16-byter

.WtH` * s.-ZKeSZsK ~ Полная программа.

.W ~ Функциональное время. В то время как A (значение) верно, значение = B (значение).
                 ~ Окончательное значение возвращается.
  tH ~ A, условие: является ли значение [1:] правдивым? Длина ≥ 2?
    `* s.-ZKeSZsK ~ B, сеттер.
       .- ~ Вычитание Bagwise, используемое для удаления старшей цифры, с ...
         Z ~ текущее значение Z, и ...
          KeSZ ~ старшая цифра Z (в виде строки). Также присваивает переменной K.
      Приведено к целому числу.
     * ~ Умножается на ...
              sK ~ старшая цифра
    `~ Преобразовать в строку.

18-byter

.WgHT * s.-`ZKeS`ZsK ~ Полная программа.

.W ~ Функциональное время. В то время как A (значение) верно, значение = B (значение).
                   ~ Окончательное значение возвращается.
  gHT ~ A, условие: значение (H) ≥ 10?
     * s.-`ZKeS`ZsK ~ B, сеттер.
       .- ~ Bagwise вычитание (используется для удаления первого вхождения).
         `Z ~ Строковое представление Z.
           KeS`Z ~ И самый высокий (лексикографически) символ Z (самая высокая цифра).
                     Он также назначает его переменной с именем K.
      s ~ приведение к целому числу.
     * ~ Умножить на ...
                ск ~ К приведен к инт.

Быть так близко к Желе в таких соревнованиях очень хорошо для Pyth IMO :-)


6

Шелуха , 14 13 12 байт

Спасибо Згарбу за сохранение 1 байта.

Ω≤9oṠS*od-▲d

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

Объяснение:

Ω≤9            Repeat the following function until the result is ≤ 9
           d     Convert to a list of digits
         -▲      Remove the largest one
       od        Convert back to an integer
   oṠS*          Multiply by the maximum digit

12 байтов с некоторой перестановкой.
Згарб

@Zgarb Спасибо, я искал что-то подобное.
H.PWiz

6

R , 99 95 байтов

f=function(x)"if"(n<-nchar(x)-1,f(10^(n:1-1)%*%(d=x%/%10^(n:0)%%10)[-(M=which.max(d))]*d[M]),x)

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

Рекурсивная функция. Добавление f(number)в нижний колонтитул можно использовать для проверки других значений number. Простая реализация, dпредставляет собой список цифр и 10^(n:2-2)%*%d[-M]вычисляет число с удалением самой большой цифры.


5

Python 2 , 72 байта

f=lambda n:`n`*(n<=9)or f(int(`n`.replace(max(`n`),'',1))*int(max(`n`)))

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


1
... Я отлаживал глупую ошибку в этом . Черт, я получил ниндзя.
полностью человек

Я получаю ошибку на входе 9
RoryT

Это похоже на неудачу для контрольного примера 432969. «ValueError: недопустимый литерал для int () с основанием 10: ''»
Джеймс Вебстер

@JamesWebster должен быть исправлен сейчас.
FlipTack

1
@recursive Нет, так как тогда, если nбыло бы 0, то n*(n<=9)все равно было бы равно ложному значению 0, что заставляло бы рекурсию продолжаться и вызывать ошибку, тогда как строка '0'является истинным значением, и поэтому рекурсия была остановлена.
FlipTack


4

Желе , 15 байт

D×Ṁ$œṡṀ$FḌµ>9µ¿

Попробуйте онлайн! или посмотрите набор тестов .

Как?

D×Ṁ$œṡṀ$FḌµ>9µ¿ - Link: number, n
              ¿ - while:
             µ  - ...condition (monadic):
            9   -    literal 9
           >    -    loop value greater than (9)?
          µ     - ...do (monadic):               e.g. 432969
D               -    convert to a decimal list        [4,3,2,9,6,9]
   $            -    last two links as a monad:
  Ṁ             -      maximum                         9
 ×              -      multiply (vectorises)          [36,27,18,81,54,81]
       $        -    last two links as a monad:
      Ṁ         -      maximum                         81
    œṡ          -      split at first occurrence      [[36,27,18],[54,81]]
        F       -    flatten                          [36,27,18,54,81]
         Ḍ      -    convert from base 10              389421  (i.e. 360000 + 27000 + 1800 + 540 + 81)


4

C # (.NET Core) , 126 байт

int F(int n){var x=(n+"").ToList();var m=x.Max();x.RemoveAt(x.IndexOf(m));return n>9?F(int.Parse(string.Concat(x))*(m-48)):n;}

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


Добро пожаловать в PPCG! Вы можете удалить пробел .
Эрик Outgolfer

@EriktheOutgolfer Спасибо, пропустил это.
Тиммех

1
@totallyhuman Спасибо, до 137 после некоторого рефакторинга.
Тиммех

Вы можете перейти if(n<10)return n;...return F(...);к одному возврату с помощью ternary-if, например так: int F(int n){var x=(n+"").ToList();var m=x.Max(d=>d);x.RemoveAt(x.IndexOf(m));return n<10?n:F(int.Parse(string.Concat(x))*(m-48));}( 131 байт )
Кевин Круйссен,

Я думаю, что вы должны включить using System.Linq;(18 байт) в байтовый счет.
Ян Х.

4

APL (Dyalog) , 36 35 33 байта

-1 из-за обновленных спецификаций OP. -2 благодаря нгн.

Функция анонимного молчаливого префикса. Принимает целое число в качестве аргумента.

{⍵>9:∇(⌈/×10⊥⊂⌷⍨¨⍳∘≢~⊢⍳⌈/)⍎¨⍕⍵⋄⍵}

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

{... }функция где аргумент:

⍵>9: если аргумент больше 9, то:

  ⍕⍵ отформатировать (stringify) аргумент

  ⍎¨ выполнить (оценить) каждый (мы получаем цифры как числа)

  () Применить следующую молчаливую функцию к тем

   ⌈/ самая большая цифра

   × раз

   10⊥ Расшифровка базы-10 (собирает цифры)

    все цифры

   ⌷⍨¨ индексируется каждым из

   ⍳∘≢я ndices из числа цифр

    отличается от

   ⊢⍳⌈/ самая большая цифра я ndex во всем списке цифр

   рекурсировать (т.е. называть себя) на этом

 еще

   вернуть аргумент без изменений


Не должно >10быть >9?
Эрик Outgolfer

@EriktheOutgolfer Возможно, но OP на самом деле неясно (противоречиво) об этом.
Адам

Это правда, но >9сэкономит байт.
Эрик Outgolfer

@EriktheOutgolfer Обновлено.
Адам

@ Adám ∇ вместо ⍣ = для -1 байта: {⍵> 9: ∇ (⌈ / ... ⋄⍵}
нгн

3

Perl 6 ,  45  41 байт

{($_,{$/=.comb.max;S/"$/"//*$/}...10>*).tail}

Попробуй это

{($_,{S/"{.comb.max}"//*$/}...10>*).tail}

Попробуй это

Expanded:

{  # bare block lambda with implicit parameter 「$_」

  (  # generate the sequence

      $_,                      # start the sequence with the input

      {                        # generate the rest of the values in the sequence

          S/                   # find and replace (not in-place)
            "{  .comb.max  }"  # find the max digit and match against it
          //                   # replace it with nothing
          *                    # multiply the result with
          $/                   # the digit that was removed
      }

      ...                      # keep generating values until

      10 > *                   # the value is less than 10

  ).tail                       # get the last value from the sequence
}

3

Сетчатка , 67 байт

{1`(..+)?
1$&;$&
O`\G\d
.+((.);.*?)\2
$1
\d+
$*
1(?=.*;(1+))|.
$1
1

Попробуйте онлайн! Ссылка включает тесты достаточно быстро, чтобы не забить сервер Денниса. Объяснение:

{1`(..+)?
1$&;$&

Для двухзначных чисел это дублирует число с ;разделителем, добавляя префикс 1 к дубликату. Для однозначных чисел это префикс 1;к номеру.

O`\G\d

Сортировать цифры дубликата. (Для однозначных чисел это не имеет никакого эффекта.)

.+((.);.*?)\2
$1

Найдите первое вхождение самой большой цифры и удалите ее, а также другие цифры в дубликате и дополнительный 1, который был добавлен ранее. (Для однозначных чисел совпадение не удается, так что это ничего не делает.)

\d+
$*
1(?=.*;(1+))|.
$1
1

Умножьте число на цифру. Для однозначных чисел это приводит к исходному номеру, и цикл завершается. В противном случае программа зацикливается, пока не будет достигнута одна цифра.


3

C # (.NET Core) , 177 164 + 18 байт

Благодаря @raznagul сэкономлено 13 байтов!

int f(int n){string s=n+"",m=s.Max(d=>d)+"";if(n<10)return n;var x=s.ToList();x.RemoveAt(s.IndexOf(m));int y=int.Parse(string.Join("",x))*int.Parse(m);return f(y);}

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


Вы можете изменить s.Length<2на n<10. Также вы можете удалить троичный оператор и просто return f(y)в конце, так как случай обрабатывается на ifследующем шаге рекурсии.
Разнагул

3

Java 8, 126 104 байта

n->{for(;n>9;n=new Long((n+"").replaceFirst((n=(n+"").chars().max().getAsInt()-48)+"",""))*n);return n;}

-22 байта благодаря @ OlivierGrégoire .

Объяснение:

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

n->{         // Method with long as both parameter and return-type
  for(;n>9;  //  Loop as long as the number contains more than 1 digit
    n=       //   Replace the current number with:
      new Long((n+"").replaceFirst((n=(n+"").chars().max().getAsInt()-48)+"",""))
             //    Remove the first largest digit from the number,
      *n     //    and multiply this new number with the removed digit
  );         //  End of loop
  return n;  //  Return the result
}            // End of method


1
104 байта (то же, что и выше, но итеративное, а не рекурсивное, также: n>9и возвращать условия вместо n<10).
Оливье Грегуар

2

Jq 1,5 , 86 байт

until(.<10;"\(.)"|(./""|max)as$v|index($v)as$x|.[:$x]+.[1+$x:]|tonumber*($v|tonumber))

расширенный

until(
    .<10                    # until number is below 10
  ; "\(.)"                  # convert to string
  | (./""|max) as $v        # find largest digit, call it $v
  | index($v) as $x         # find index of digit
  | .[:$x]+.[1+$x:]         # remove digit
  | tonumber*($v|tonumber)  # convert back to number and multiply by $v
)

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



2

Lua, 137 108 байт

function f(n)while n>9 do b="0"g=b.gsub g(n,".",function(m)b=math.max(m,b)end)n=b*g(n,b,"",1)end print(n)end

Спасибо Джонатану S за то, что он выложил в гольф 29 байтов.

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



Спасибо. Это выглядит достойным ответа самостоятельно - будет ссылка на сообщение, которое вы делаете для него, в противном случае будет редактировать и кредит.
MCAdventure10

Просто отредактируйте его. Это все еще ваш код, я не написал его с нуля.
Джонатан С.

2

D , 188 186 185 байт

import std.conv,std.algorithm;T f(T,U=string)(T u){if(u<10)return u;T[]r;u.text.each!(n=>r~=n.to!T-48);T m=r.maxElement;U s;r.remove(r.maxIndex).each!(n=>s~=n.to!U);return f(m*s.to!T);}

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

Я очень ненавижу ленивую оценку. Любые советы приветствуются!


2

Луа, 154 байта

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

n=...z=table
while n+0>9 do
t={}T={}n=n..''n:gsub(".",function(c)t[#t+1]=c T[#T+1]=c
end)z.sort(t)x=t[#t]z.remove(T,n:find(x))n=z.concat(T)*x
end
print(n)

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

Пояснения

n=...                    -- define n as a shorthand for the argument
z=table                  -- define z as a pointer to the object table
while n+0>9              -- iterate as long as n is greater than 9
do                       -- n+0 ensure that we're using a number to do the comparison
  t={}                   -- intialise two tables, one is used to find the greatest digit
  T={}                   -- the other one is used to remove it from the string
  n=n..''                -- ensure that n is a string (mandatory after the first loop)
  n:gsub(".",function(c) -- apply an anonymous function to each character in n
               t[#t+1]=c -- fill our tables with the digits
               T[#T+1]=c
             end)        
  z.sort(t)              -- sort t to put the greatest digit in the last index
  x=t[#t]                -- intialise x to the value of the greatest digit
  z.remove(T,n:find(x))  -- remove the first occurence of x from the table T 
                         -- based on its position in the input string
  n=z.concat(T)*x        -- assign the new value to n
end                      -- if it still isn't a single digit, we're looping over again
print(n)                 -- output the answer

2

PowerShell , 123 байта

[Collections.ArrayList]$a=[char[]]"$args"
while(9-lt-join$a){$a.remove(($b=($a|sort)[-1]));$a=[char[]]"$(+"$b"*-join$a)"}$a

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

Ooof. Массивы PowerShell являются неизменяемыми, поэтому нам нужно использовать длительное [Collections.ArrayList]приведение здесь, чтобы мы могли вызвать .remove()позже.

Принимает ввод $args, преобразует его в строку, затем char-array, затем в ArrayList. Хранит это в $a. Затем мы whileзациклимся, пока не достигнем уровня или ниже 9. Каждая итерация, мы вызываем .removeна наибольшем элементе $a(сделано sortи с последним элементом[-1]$b к самому ), сохраняя самый большой элемент одновременно. Это работает, потому что значения ASCII сортируются так же, как и буквенные цифры.

Затем, мы $aснова charвычисляем , снова как -array (и ArrayListнеявно), приводя нашу $b(которая в настоящее время является char) к строке, затем к int +и умножая это на $a -joined в строку (неявно приводим к int). Это удовлетворяет части задачи «умножить на D».

Наконец, как только мы выходим из цикла, мы помещаем $aв конвейер и вывод неявный.


2

Пип , 22 21 байт

Wa>9a:aRAa@?YMXax*:ya

Принимает ввод в качестве аргумента командной строки. Проверьте все контрольные примеры: попробуйте онлайн!

объяснение

Ungolfed, с комментариями:

                 a is 1st cmdline arg
W a>9 {          While a > 9:
  Y MXa           Yank max(a) into y
  a RA: a@?y ""   Find index of y in a; replace the character at that position with ""
  a *: y          Multiply a by y
}
a                Autoprint a

В версии для гольфа тело петли сведено в одно выражение:

a:aRAa@?YMXax*:y
        YMXa      Yank max(a)
     a@?          Find its index in a
  aRA       x     Replace at that index with x (preinitialized to "")
             *:y  Multiply that result by y (using : meta-operator to lower the precedence)
a:                Assign back to a


2

Java 8: 115 байт


-10 байтов благодаря Джо Кингу

К сожалению, вы не можете вызывать лямбда-функцию рекурсивно, поэтому для заголовка метода требуются дополнительные 11 байтов. Я знаю, что вместо этого есть более короткий ответ Java, но я решил придумать это самостоятельно.

long f(long n){int m=(n+"").chars().max().getAsInt()-48;return n>9?f(new Long((n+"").replaceFirst(""+m,""))*m):n;};

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


Вы можете переместить -48от карты до конца mопределения. Попробуйте онлайн! У вас также есть дополнительные пробелы в вашей ссылке TIO
Джо Кинг

@ Шучу, спасибо.
Бенджамин Уркхарт

1

J, 40 байт

((]*<^:3@i.{[)>./)&.(10&#.inv)^:(9&<)^:_

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

объяснение

(      iterate                   )^:(9&<)^:_    NB. keep iterating while the number is > 9
 (     stuff         )&.(10&#.inv)              NB. convert to digits, do stuff, convert back to number
 (           )>./)                              NB. stuff is a hook, with max digit >./  on the right
 (]*<^:3@i.{[)                                  NB. so that in this phrase, ] means "max" and [ means "all digits"
  ]                                             NB. the max digit...
   *                                            NB. times...        
    <^:3@                                       NB. triple box...
         i.                                     NB. the first index of the max in the list of all digits
           {                                    NB. "from" -- which because of the triple box means "take all indexes except..."
            [                                   NB. from all the digits of the number

1
Я узнал о выборе тройной коробки от вас сегодня, спасибо!
Гален Иванов

1

PowerShell , 230 байт

$n="$args";do{$n=$n.ToString();$a=@();0..$n.Length|%{$a+=$n[$_]};$g=[convert]::ToInt32(($a|sort|select -last 1),10);[regex]$p=$g.ToString();[int]$s=$p.replace($n,'',1);if($n.Length-eq1){$n;exit}else{$r=$s*$g}$n=$r}until($r-lt10)$r

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

Потрачено слишком много на все типы литья.



1

постоянный ток , 98 85 байт

?dsj[0dsosclj[soIlc^sr0]sn[I~dlo!>nrlc1+scd0<i]dsixljdlr%rlrI*/lr*+lo*dsj9<T]sT9<Tljp

Большое спасибо за этот ответ за идею использования~ при извлечении цифр из числа, что привело к двум сохраненным байтам по сравнению с исходной версией кода.

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

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


1

Баш, 80 байт

Используются пакеты Core Utilities (для sortа tail) и grep.

while((n>9));do m=$(grep -o .<<<$n|sort|tail -n1);n=$((${n/$m/}*m));done;echo $n

Как это работает?

while (( n > 9 )); do  # C-style loop conditional
    grep -o .          # Separate the string into one char per line
              <<< $n   # Use the content of variable `n` as its stdin
    | sort             # Pipe to `sort`, which sorts strings by line
    | tail -n 1        # Take the last line

m=$(                 ) # Assign the output of the command chain to `m`
n=$((          ))      # Assign the result of the evaluation to n
     ${n/$m/}          # Replace the first occurrence of $m with empty
             *m        # ... and multiply it by the value of `m`
done; echo $n          # After loop, print the value of `n`
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.