Лучшая база - 10 ... Достигнем!


40

Входные данные:

Положительное целое число n, состоящее из цифр в диапазоне 0-9 .

Вызов:

Если d является старшей цифрой в целом числе, предположим, что основание числа d + 1 . Например, если целое число равно 1256, то вы должны предположить, что оно находится в base-7 , если это 10110, то вы должны предположить, что это base-2 (двоичное), а если это 159, то это десятичное число.

Теперь делайте следующее до тех пор, пока не достигнете 1: достичь целого числа от 10 до 10 или 2 2: достичь целого числа из одной цифры.

  1. Преобразовать целое число из base- (d + 1) в base-10
  2. Найдите основание этого нового целого числа (опять же, base- (d + 1), где d - самая большая цифра в новом числе)
  3. Переходите к шагу 1 .

Примеры:

Предположим, что ввод n = 413574 . Наибольшая цифра d = 7 , так что это основание-8 (восьмеричное). Переведите это в десятичное число и получите 137084 . Наибольшая цифра d = 8 , так что это основание-9 . Переведите это в десятичное число и получите 83911 . Наибольшая цифра - 9 , так что это десятичное число, и мы остановимся. Выход должен быть 83911 .

Предположим, что ввод n = 13552 . Наибольшая цифра d = 5 , так что это base-6 . Переведите это в десятичное число и получите 2156 . Наибольшая цифра d = 6 , так что это основание-7 . Переведите это в десятичное число и получите 776 . Наибольшая цифра d = 7 , так что это основание-8 . Переведите это в десятичное число и получите 510 . Наибольшая цифра d = 5, так что это base-6 . Переведите это в десятичное число и получите 186 . Самая высокая цифра - 8 , поэтому это база-9 . Переведите это в десятичное число и получите 159 . Самая высокая цифра 9 , так что это десятичное число, и мы остановимся. Выход должен быть 159 .

Предположим, что ввод n = 17 . Это даст нам 15 , затем 11 , затем 3 , которые мы выведем, так как это одна цифра.


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

5
5

17
3

999
999

87654321  (base-9 -> 42374116 in decimal -> base-7 -> 90419978 in decimal) 
9041998

41253  (5505 -> 1265 -> 488 -> 404 -> 104 -> 29)
29

Заметки:

  • Стандартные правила, касающиеся ввода / вывода, лазеек и т. Д. Вы можете принять ввод как строку
  • Пояснения приветствуются
  • Вы можете использовать встроенные команды преобразования базы
    • Решения, в которых не используются встроенные функции преобразования базовых кодов языка (если они существуют), приветствуются, даже если они оказываются намного дольше, чем очевидный подход с использованием встроенных функций.

Видимо, это OEIS A091047 .


2
По-видимому, я люблю матрицы , поэтому я решил вместо этого выполнить задачу преобразования базы .
Стьюи Гриффин

34
"Лучшая база - это 10" ... На какой базе написано "10"?
Оливье Грегуар

5
@ OlivierGrégoire Это умная штука ... На чем бы мы ни остановились, это будет верное утверждение!
Стьюи Гриффин

@StewieGriffin Но как ты это читаешь? «10» имеет разные названия в каждой базе.
user11153

10
Ну, это зависит от базы ... или, как сказала бы Меган, "это все о той базе, о той базе, без проблем" ;-)
Стьюи Гриффин,

Ответы:


20

Mathematica, 56 байт

#//.x_/;(b=Max[d=IntegerDigits@x]+1)<11:>d~FromDigits~b&

Попробуйте онлайн!(Используя математику.)

Я решил проверить, как выглядит последовательность:

введите описание изображения здесь

А вот график количества шагов, необходимых для поиска результата:

введите описание изображения здесь

(Нажмите для увеличения версий. См. Историю изменений для графиков только до n = 1000. )

Выглядит как очень интересная смесь крупномасштабной структуры и мелкого хаоса. Интересно, что случилось с более широкими промежутками около 30 000 и 60 000?


4
@StewieGriffin должен быть слева. Небольшие пробелы есть, потому что числа, ведущие к кратному степени 10, содержат a 9, поэтому они уже находятся в базе 10. Но для 30k и 60k кажется, что числа с 8 или даже 7 (должны были бы проверьте) вместо того, чтобы эти 9 всегда становились основанием 10 не более чем за один шаг.
Мартин Эндер

@StewieGriffin Чтобы быть точным, все числа в диапазоне [28051, 28888] являются основанием 9 и переводятся в числа вида 19xxx, таким образом, в значительной степени удваивая этот разрыв.
начальник

Ах, понял ... :) Для справки: я знал, почему были пробелы с левой стороны степеней 10-х ... Странными были только двойные зазоры (почему 30/60, а не 20 / 40/50). Теперь я вижу, что числа в диапазоне 28xxx -> 19xxx, но 38xxx -> 26xxx, а не 29xxx.
Стьюи Гриффин

10

Java 8, 172 166 163 152 151 140 138 116 114 99 байт

s->{for(Integer b=0;b<10&s.length()>1;s=""+b.valueOf(s,b=s.chars().max().getAsInt()-47));return s;}

Принимает вход как String.

-64 байта благодаря @ OlivierGrégoire . И тут я подумал, что мои первые 172 были не так уж плохи ..;)

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

Объяснение:

s->{                    // Method with String as parameter and return-type
  for(Integer b=0;b<10  //  Loop as long as the largest digit + 1 is not 10
      &s.length()>1;    //  and as long as `s` contains more than 1 digit
    s=""+               //   Replace `s` with the String representation of:
         b.valueOf(s,   //    `s` as a Base-`b` integer
          b=s.chars().max().getAsInt()-47)
                        //     where `b` is the largest digit in the String + 1
  );                    //  End of loop
  return s;             //  Return result-String
}                       // End of method

1
Обещание сохранять спокойствие? Хорошо, поехали s->{for(Integer b=0;b<10&s.length()>1;)s=""+b.valueOf(s,b=s.chars().max().getAsInt()-47);return s;}. Также я удалил большинство своих комментариев, так как они сейчас совершенно неактуальны ( bэто база, ваша a; и sномер, над которым мы работаем).
Оливье Грегуар

1
Я попытался изменить это, чтобы сбрить некоторые байты с: Integer b;return(b=s.chars().max().getAsInt()-47)>9|s.length()<2?s:c(""+b.valueOf(s,b));(88), но я новичок в коде гольф. Это отрывок, верно? Есть ли способ объявить это как метод без необходимости добавлять public String c(String s)?
Лорд Фаркваад

1
@LordFarquaad Вам не нужно public, но я боюсь, что вам действительно придется использовать String c(String s){}для рекурсивных вызовов, даже в Java 8. Когда вы создаете лямбда- выражение java.util.function.Function<String, String> c=s->{Integer b;return(b=s.chars().max().getAsInt()-47)>9|s.length()<2?s:c‌.apply​(""+b.valueOf(s,b));}или интерфейс, использующий interface N{String c(String s);}N n = s->{Integer b;return(b=s.chars().max().getAsInt()-47)>9|s.length()<2?s:n.c‌​(""+b.valueOf(s,b));};его, вы получите « самостоятельную ссылку в инициализаторе». ошибка »в обоих случаях. Но тем не менее очень хороший подход!
Кевин Круйссен

Ах, я полагаю, тогда я разложил несколько байтов. Но спасибо за помощь! Я буду помнить об этом, двигаясь вперед.
Лорд Фаркваад

8

Pyth, 9 байт

ui`GhseS`

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

Объяснение:

ui`GhseS`
ui`GhseS`GQ    Implicit variable introduction
u         Q    Repeatedly apply the following function until the value repeats,
               starting with Q, the input.
        `G     Convert the working value to a string.
      eS       Take its maximum.
     s         Convert to an integer.
    h          Add one.
 i`G           Convert the working value to that base

Немного странно, как вы использовали лямбду с двумя переменными, заканчивающуюся использованием одной переменной ... и она не выдавала ошибки. О, две переменные Qи Qя понял.
Эрик Outgolfer

@EriktheOutgolfer Не совсем. uбез третьего ввода применяется до повторения, тогда как с третьим вводом применяется фиксированное число раз. uЛямбда имеет Gи H, но вам не нужно использовать H.
Исаак

На самом деле замена Gна Hимела бы тот же результат ... Кстати, неявная переменная есть G?
Эрик Outgolfer

@EriktheOutgolfer Неявная переменная есть G, да. Hотсчитывает от 0 с каждой итерацией, поэтому он совершенно другой. Я не совсем уверен, о чем ты говоришь. Вот пример программы , чтобы показать вам , что происходит: pyth.herokuapp.com/...
isaacg

6

JavaScript (ES6), 63 57 54 53 байта

f=a=>a>9&(b=Math.max(...a+""))<9?f(parseInt(a,b+1)):a

Сохранено 8 байтов благодаря Shaggy и Dom Hastings

f=a=>a>9&(b=Math.max(...a+""))<9?f(parseInt(a,b+1)):a;

console.log(f("413574"))


Ударь меня к этому. Я думаю, вы могли бы сэкономить несколько байтов с помощью +a>9||b<9реверсной троицы.
Лохматый

1
@ Шэгги редактировать: я тупой
Том

1
Не будь таким строгим с собой, Том! Ты не тупой ,,, но ты определенно не такой умный, как @Shaggy!
Стьюи Гриффин

1
Альтернатива для 55 байтовf=n=>n>9&&(k=Math.max(...n+"")+1)<10?f(parseInt(n,k)):n
Дом Гастингс

@DomHastings Спасибо за улучшения! :)
Том

5

Python 3 , 91 78 76 75 73 байта

@Emigna сбрил 5 байтов. @FelipeNardiBatista сохранил 1 байт. @ RomanGräf сэкономил 2 байта

i=input()
while'9'>max(i)and~-len(i):i=str(int(i,int(max(i))+1))
print(i)

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


объяснение

i=input()                                  - takes input and assigns it to a variable i
while '9'>max(i)and~-len(i):               - repeatedly checks if the number is still base-9 or lower and has a length greater than 1
    i=str(...)                             - assigns i to the string representation of ...
          int(i,int(max(i))+1)             - converts the current number to the real base 10 and loops back again
print(i)                                   - prints the mutated i

5

05AB1E , 10 5 байт

5 байтов сохранено благодаря волшебной урне осьминога

F§Z>ö

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

[©Z>öD®Q#§

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

объяснение

[             # start a loop
 ©            # store a copy of the current value in the register
  Z>          # get the maximum (digit) and increment
    ö         # convert the current value to base-10 from this base
     D        # duplicate
      ®Q#     # break loop if the new value is the same as the stored value
         §    # convert to string (to prevent Z from taking the maximum int on the stack)

Кроме того, вы не можете просто использовать тFZ>ö§? Видя, как количество итераций ( как видно здесь ) кажется плато? Если вы хотите получить техническую информацию, скорость, с которой возрастают итерации, вероятно, является логарифмической ... Так что вы можете просто использовать что-то вроде: DFZ>ö§и заявить, что он не будет работать слишком долго n. ИЛИ, может быть, даже: T.n>FZ>ö§для непосредственного расчета количества итераций как log_10(n).
Волшебная Осьминог Урна

@MagicOctopusUrn: Да, теперь, когда вы упомянули об этом, поскольку последовательность определенно кажется более медленной, чем линейная, она F§Z>öдолжна сработать.
Эминья

Я думаю, что вы можете удалить §.
Эрик Outgolfer

@EriktheOutgolfer: к сожалению нет. Если мы удалим §, Zвозьмем старшее число в стеке вместо старшего числа в числе на вершине стека.
Эминья

@ Emigna А ?
Эрик Outgolfer

3

APL (Dyalog) , 20 16 байтов

Принимает и возвращает строку

((⍕⊢⊥⍨1+⌈/)⍎¨)⍣≡

()⍣≡ Применять следующую функцию, пока два последовательных термина не будут идентичны:

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

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

  ⌈/ найти максимум аргумента

  1+ добавить один

  ⊢⊥⍨ оценить аргумент в этой базе

   формат (stringify, при подготовке к другому применению внешней функции)

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



3

Mathematica, 52 байта

FromDigits[s=IntegerDigits@#,Max@s+1]&~FixedPoint~#&

Чистая функция, принимающая неотрицательное целое число в качестве входных данных и возвращающая неотрицательное целое число. Использует ту же основную механику, FromDigits[s=IntegerDigits@#,Max@s+1]что и ответ Jenny_mathy , но использует FixedPointитерацию.


3

Perl 6 , 49 байт

{($_,{.Str.parse-base(1+.comb.max)}...*==*).tail}

Попробуй это

Expanded:

{
  (

    $_,                 # seed the sequence with the input

    {
      .Str
      .parse-base(      # parse in base:
        1 + .comb.max   # largest digit + 1
      )
    }

    ...                 # keep generating values until

    * == *              # two of them match (should only be in base 10)

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


2

Пип , 17 байт

Wa>9>YMXaaFB:1+ya

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

объяснение

Это было весело - я должен был вытащить операторы сравнения цепочек.

Мы хотим зациклить, пока число не станет одной цифрой ИЛИ не содержит 9. Эквивалентно, мы хотим зациклить, пока число состоит из нескольких цифр И не содержит 9. Эквивалентно, зациклить, пока число больше 9 И максимальная цифра не равна менее чем 9: a>9>MXa.

Wa>9>YMXaaFB:1+ya
                   a is 1st cmdline arg (implicit)
     YMXa          Yank a's maximum digit into the y variable
Wa>9>              While a is greater than 9 and 9 is greater than a's max digit:
         aFB:1+y    Convert a from base 1+y to decimal and assign back to a
                a  At the end of the program, print a

2

Python 2 , 60 59 56 53 байта

Сэкономили 4 байта благодаря Фелипе Нарди Батиста
Сэкономили 3 байта благодаря овам

f=lambda x,y=0:x*(x==y)or f(`int(x,int(max(x))+1)`,x)

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

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


почему бы не использовать x==y and x or ...как xникогда 0(база 1). или даже(x==y)*x or ...
Фелипе Нарди Батиста

@FelipeNardiBatista: Спасибо! Я пытался x and x==y or ..., но это не сработало, но я не слишком хорошо
Emigna

@ovs: Ты прав. Благодарность!
Эминья

@FelipeNardiBatista "Входные данные: положительное целое число n, состоящее из цифр в диапазоне 0-9." 0 все еще допустимый ввод, и теперь код отклоняет его.
Мачта

@Mast: К счастью для нас, 0 не является положительным целым числом, поэтому оно не будет передано в качестве входных данных.
Эминья

2

C #, 257 244 243 244 233 222 байта

using System.Linq;z=m=>{int b=int.Parse(m.OrderBy(s=>int.Parse(s+"")).Last()+""),n=0,p=0;if(b<9&m.Length>1){for(int i=m.Length-1;i>=0;i--)n+=int.Parse(m[i]+"")*(int)System.Math.Pow(b+1,p++);return z(n+"");}else return m;};

Ну, C # всегда занимает много байтов, но это просто смешно. Ни одна из встроенных программ не может обработать произвольную базу, поэтому мне пришлось рассчитывать конверсию самостоятельно. Ungolfed:

using System.Linq;
z = m => {
int b = int.Parse(m.OrderBy(s => int.Parse(s + "")).Last()+""), n = 0, p = 0; //Get the max digit in the string
if (b < 9 & m.Length > 1) //if conditions not satisfied, process and recurse
{
    for (int i = m.Length - 1; i >= 0; i--)
        n += int.Parse(m[i] + "") * (int)System.Math.Pow(b+1, p++); //convert each base-b+1 representation to base-10
    return z(n + ""); //recurse
}
else return m; };

1

Mathematica, 92 байта

f[x_]:=FromDigits[s=IntegerDigits@x,d=Max@s+1];(z=f@#;While[d!=10&&Length@s>1,h=f@z;z=h];z)&

1

Javascript (ES6) с функцией 0 стрелки, 74 байта

function f(a){a>9&&b=Math.max(...a)<9&&f(parseInt(a,b+1));alert(a)}f('11')

3
Добро пожаловать в PPCG! :) Это, вероятно, очень хороший ответ, но я не могу сказать без объяснения причин. Я (и, возможно, другие) никогда не одобряю ответы, которые не содержат объяснений.
Стьюи Гриффин

1
Почему вы звоните f('11')после функции? Если я не пропущу что-то, что выглядит только как использование, а не как часть представления. Если это так, вы должны вынуть его из раздела кода и вставить в свое объяснение (когда вы добавляете его) и обновить количество байтов до 67.
PunPun1000

1

К4 , 19 байт

Решение:

{(1+|/x)/:x:10\:x}/

Примеры:

q)\
  {(1+|/x)/:x:10\:x}/413574
83911
  {(1+|/x)/:x:10\:x}/13552
159
  {(1+|/x)/:x:10\:x}/17
3
  {(1+|/x)/:x:10\:x}/41253
29    

Объяснение:

Используйте /:встроенные для преобразования базы.

{(1+|/x)/:x:10\:x}/ / the solution
{                }/ / converge lambda, repeat until same result returned
            10\:x   / convert input x to base 10 (.:'$x would do the same)
          x:        / store in variable x
 (     )/:          / convert to base given by the result of the brackets
    |/x             / max (|) over (/) input, ie return largest
  1+                / add 1 to this

1

Котлин , 97 байт

fun String.f():String=if(length==1||contains("9"))this else "${toInt(map{it-'0'}.max()!!+1)}".f()

украшенный

fun String.f(): String = if (length == 1 || contains("9")) this else "${toInt(map { it - '0' }.max()!! + 1)}".f()

Тест

fun String.f():String=if(length==1||contains("9"))this else "${toInt(map{it-'0'}.max()!!+1)}".f()
val tests = listOf(
        5 to 5,
        17 to 3,
        999 to 999,
        87654321 to 9041998,
        41253 to 29
)

fun main(args: Array<String>) {
    tests.forEach { (input, output) ->
        val answer = input.toString().f()
        if (answer != output.toString()) {
            throw AssertionError()
        }
    }
}

TIO

TryItOnline




0

C 159 157 байт

#include <stdlib.h>
char b[99];i=0;m=-1;c(n){do{m=-1;sprintf(b,"%d",n);i=0;while(b[i]){m=max(b[i]-48,m);i++;}n=strtol(b,0,++m);}while(b[1]&&m<10);return n;}

0

Scala , 119 байт

if(x.max==57|x.length==1)x else{val l=x.length-1
f((0 to l).map(k=>(((x(k)-48)*math.pow(x.max-47,l-k))) toInt).sum+"")}

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

Scala , 119 байт

if(x.max==57|x.length==1)x else f((0 to x.length-1).map(k=>(((x(k)-48)*math.pow(x.max-47,x.length-1-k))) toInt).sum+"")

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

Оба метода работают одинаково, но в первом я помещаю x.length-1переменную, а во втором - нет.

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