Лучшая база - 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().ge‌tAsInt()-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.