Пандигитальное удвоение


14

Вдохновленный этим CMC

Если положительное целое число больше 0, выполните с ним следующую операцию:

  • Если 1234567890хотя бы один раз все десять одинарных цифр ( ) находятся в числе, выведите счетчик и выйдите из программы.
  • В противном случае удвойте число и повторите, увеличив счет.

Счет начинается с 0 и является количеством удвоений ввода. Например, если бы ввод был 617283945, его нужно было бы удвоить один раз, потому что 1234567890 содержит все 10 цифр.

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

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

input => output

617283945 => 1
2 => 67
66833 => 44
1234567890 => 0
100 => 51
42 => 55

Можем ли мы принять ввод как строку?
Стивен

@ Стефан, вы можете принять ввод как строку.
Caird Coneheringaahing

3
Гарантируется ли, что для любого nсуществует нечто kтакое, что nkявляется пандигитальным? Я хотел бы увидеть доказательство.
shooqie

1
@bfontaine Chat Mini Challenge
caird coinheringaahing

3
@ Shooqie Доказательство! Для любого n, который взаимно прост до 10, он также взаимно прост до 10 ^ 10, и поэтому существует некоторое k, такое что nk равно 1 mod 10 ^ 10. Тогда 1234567890 * nk = 1234567890 mod 10 ^ 10, поэтому каждая цифра обязательно появляется хотя бы один раз. Если нет, умножьте на 2, 5 или 25, если необходимо, чтобы последняя ненулевая цифра была взаимно простой с 10, и вариант приведенного выше доказательства работает (формально, n = 10 ^ m * p, где p удовлетворяет вышеуказанному условию , тогда 1234567890 * p * k, как указано выше, является pandigital, поэтому 1234567890 * p * k * 10 ^ m = 1234567890 * k * n равно). :)
Б. Мехта

Ответы:



4

J , 24 23 байт

(]1&(+$:)2**)10>#@~.@":

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

объяснение

(]1&(+$:)2**)10>#@~.@":  Input: integer n
                     ":  Format as string
                  ~.@    Unique
                #@       Length
             10>         Less than 10
           *             Multiply, gives n if previous was true, else 0
         2*              Multiply by 2
 ]                       Get the previous condition
  1&(   )                Execute this if true on 2n, else return 0
      $:                   Recurse
  1  +                     Add 1

Ницца. Я застрял на сборе результатов, не думал об использовании этого типа рекурсивной функции.
Конор О'Брайен,

4

05AB1E , 11 10 байт

-1 байт благодаря Скоттинету

[D9ÝåË#·]N

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

[          // Start infinity loop
 D         // Duplicate current value (or input)
  9Ý       // Push [0,1,2,3,4,5,6,7,8,9]
    å      // Does each exist in the current value
     Ë#    // Break if all equal (if every digit exists)
       ·   // Else double the current value
        ]N // End loop and print the number of times through the loop


@ Scottinet Спасибо! Я не знаю, как я это пропустил.
Райли

@riley собирался сказать use x но это тоже 10 ... Хороший ответ. Мысль xизбавилась бы от этого D, но это та же идея.
Волшебная урна осьминога

3

Perl 6 ,31 28 байтов (27 символов)

-3 байта благодаря @ Джошуа

{($_,2×*...*.comb.Set>9)-1}

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

Объяснение: Все та же конструкция для рекурсивной генерации списков. Первый элемент заданное число ( $_), каждый следующий элемент 2 раза больше предыдущего ( 2×*- мы используем ×, потому что, хотя 2 байта характер, она по - прежнему один байт дешевле 2 * *), и мы делаем это до конца условие *.comb.unique>9выполнено т.е. когда в номере более 9 уникальных символов. (Технически, мы разбиваем строку на список символов с .combпомощью, приводим ее к набору с помощью .Set(конечно, наборы содержат каждый элемент только один раз) и сравниваем с 9, что переводит набор в числовой контекст, что, в свою очередь, дает его количество элементов.)

Наконец, мы вычитаем 1 из этого списка. Опять же, список приводится в числовой контекст, так что мы возвращаем на 1 меньше длины этого списка.


Вы можете использовать .Setвместо того, .uniqueчтобы сохранить 3 байта.
Джошуа

@ Джошуа, хорошая мысль! Спасибо. Я никогда не думал об этом.
Ramillies

3

JavaScript (ES6) + big.js , 84 74 73 70 байт

Спасибо @ ConorO'Brien за сохранение 10 байтов, предложив big.js вместо bignumber.js.
Спасибо @Rick Hitchcock за -1 байт
Спасибо @Shaggy за -3 байта.

f=n=>[..."4"+2**29].every(d=>RegExp(d).test(c=Big(n)))?0:1+f(c.mul(2))

Принимает ввод как строку; поддерживает до 2 69 из-за автоматического преобразования обозначений, происходящих после этой точки.

Тестовый фрагмент

f=n=>[..."4"+2**29].every(d=>RegExp(d).test(c=Big(n)))?0:1+f(c.mul(2))

;[617283945, 2, 66833, 1234567890, 100, 42].forEach(t=>console.log(`f(${t}) = `+f(t)))
<script src="https://cdn.rawgit.com/MikeMcl/big.js/c6fadd08/big.min.js"></script>

Бесконечный диапазон, 106 88 87 84 байта

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


Может быть, вы могли бы сократить BigNumberбит, используя big.js ?
Конор О'Брайен,

@ ConorO'Brien Это определенно поможет, особенно потому, что newв этом нет необходимости. Буду обновлять, спасибо!
Джастин Маринер

Сохранить один байт с f=n=>[..."0123456789"].every(d=>RegExp(d).test(c=Big(n)))?0:1+f(c.mul(2)).
Рик Хичкок,

Нам не нужно обрабатывать большие целые числа, чтобы вы могли выбросить big.js, если хотите, и вы получите 61 байт. И вы можете сохранить 3 байта, заменив строку цифр на "4"+2**29: tio.run/##BcGxDkAwEADQb2GQO41LNBZDbX7AKgbhKkSu0jZSX1/…
Shaggy

2

Желе , 12 , 11 байт

QLn⁵
ḤÇпL’

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

Должен идти быстро!

Объяснение:

        # Helper link, takes one argument 'z'
Q       # The unique digits of 'z'
 L      # Length
  n     # Does not equal
   ⁵    # 10
        #
        # Main link
  п    # While <condition> is true, run <body> and return all intermediate results
        # Condition:
 Ç      #   The helper link
        # Body:
Ḥ       #   Double the input
        # Now we have a list of all the 'z's that we passed to the helper link
    L   # Return it's length
     ’  # minus one





2

Clojure, 115 89 82 байта

-26 байтов, просто используя строку для представления списка символов (duh, в ретроспективе) и переходя от использования рекурсии к loop, что позволило мне сделать пару оптимизаций.

-7 байт, избавившись от вызова bigint. Очевидно, нам нужно обрабатывать только ввод, который не вызовет переполнения.

#(loop[n % c 0](if(empty?(remove(set(str n))"1234567890"))c(recur(* 2 n)(inc c))))

Pregolfed:

(defn pan [num]
  (loop [n num
         cnt 0]

    ; Remove all the characters from the stringified input
    ;  that are numeric. If the result is an empty list, all
    ;  the numbers were present.
    (if (empty? (remove (set (str n)) "1234567890"))
      cnt
      (recur (* 2 n) (inc cnt)))))

Вы можете сэкономить 7 байт, используя every?вместо empty? (remove …:#(loop[n % c 0](if(every?(set(str n))"1234567890")c(recur(* 2 n)(inc c)))))
bfontaine

@bfontaine О, ты прав! Благодарю. Я исправлю это позже. Благодарю.
Карцигеникат

2

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

^\d*
$&¶$&
D`.(?=.*¶)
\d{10}¶\d+|\d*¶

[5-9]
#$&
T`d`EE
T`_d#`d_`\d#
#
1
}`\d\b
$&@
@

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

^\d*
$&¶$&

Дублируйте введенный номер.

D`.(?=.*¶)

Дублируйте цифры в первом экземпляре.

\d{10}¶\d+|\d*¶

Если осталось 10 цифр, удалите оба номера, в противном случае просто удалите первую копию. Обратите внимание, что удаление обоих чисел приводит к тому, что оставшаяся часть цикла не работает.

[5-9]
#$&

Поместите #перед большими цифрами.

T`d`EE

Удвойте каждую цифру.

T`_d#`d_`\d#

Добавьте в керри.

#
1

Разобраться с ведущим керри.

}`\d\b
$&@

Добавляйте @и цикл до тех пор, пока не будут найдены все 10 цифр.

@

Распечатайте количество @добавленных s.


2

APL (Dyalog Unicode) , 19 + 2 = 21 байт

0∘{∧/⎕D∊⍕⍵:⍺⋄⍺+12×⍵}

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

Это диадический Dfn( д Прям ая е unctio п ), с 0 в качестве аргумента левого и целого числа , как справа. Поскольку предполагается, что входными данными являются только целые числа, я добавил 2 байта для аргумента 0∘в счетчик байтов.

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

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

Заголовки: я удалил их из числа байтов после некоторого чата в комнате APL, так как функция делает то, что должна, и результаты неверны только из-за настроек REPL APL по умолчанию.

⎕FR←1287Устанавливает F loat R epresentation на 128-битное десятичное число (7 - это код десятичного числа в REPL APL). ⎕PP←34Устанавливает разрешение P rint P на 34 цифры. Оба из них необходимы, так как представление по умолчанию для больших чисел в APL преобразует их в научную нотацию (например, 3.14159265359E15), что приводит к путанице в коде.

0∘{∧/⎕D∊⍕⍵:⍺⋄⍺+12×⍵}  Dyadic Dfn
0                      Fixes 0 as the left argument  
          :             If
     D                 String representation of all digits [0, 9]
                       "is in"
        ⍕⍵              String representation of the input
   ∧/                   AND-reduction. Yields 1 (true) iff all digits are in the right argument.
                       return the left argument
                       Else
                 2×⍵    Double the right arg
             ⍺+1        increment the left arg
                       Recursively call this function with the new arguments.

2

Java 8, 132 110 87 74 байта

n->{int c=0;for(;(n+"").chars().distinct().count()!=10;n*=2)c++;return c;}

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

Объяснение:

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

n->          // Method with long parameter and integer return-type
  int c=0;   //  Count-integer, starting at 0
  for(;(n+"").chars().distinct().count()!=10;
             //  Loop (1) as long as the unique amount of digits in the number are not 10
    n*=2)    //    After every iteration: multiply the input by 2
   c++;      //   Increase the count by 1
             //  End of loop (1) (implicit / single-line body)
  return c;  //  Return the counter
}            // End of method

Старые 132 байта отвечают, используя Stringввод и регулярное выражение:

n->f(n,0)int f(String n,int c){String t="";for(int i=0;i<10;t+="(?=.*"+i+++")");return n.matches(t+".*")?c:f(new Long(n)*2+"",c+1);}

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

Общее регулярное выражение, чтобы проверить, содержит ли строка все 9 цифр, становится ^(?=.*0)(?=.*1)(?=.*2)(?=.*3)(?=.*4)(?=.*5)(?=.*6)(?=.*7)(?=.*8)(?=.*9).*$, что использует положительный прогноз для всей строки.


1
111 байт (да, количество байт является «одноразрядным» ;-)
Оливье Грегуар,

Обратите внимание, что 2 никогда не сработает, потому что мы ожидаем, 2^68что первое пандигитальное число, но длинные в Java ограничены 2^63-1.
Оливье Грегуар,

1
87 байт . Спасибо reduce\ O /
Оливье Грегуар

1
74 байта . Остановка здесь ;-)
Оливье Грегуар,

1
@KevinCruijssen Я знаю, что вы уничтожили свой старый метод, но просто хочу отметить, что вы можете использовать следующее регулярное выражение для сопоставления всех 10 цифр:(?:.*?(\d)(?!.*\1)){10}
jaytea

1

Шелуха , 10 байт

←Vö>9Lud¡D

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

объяснение

        ¡D    Repeatedly double the input, collecting results in a list
 V            Return the first index where the following is true
     L          The length of
       d        the digits
      u         with duplicates removed
  ö>9           is greater than 9
←             Decrement (as Husk uses 1-indexing)

1

Mathematica, 59 48 47 46 38 байт

-9 байт благодаря Jenny_mathy.

If[!FreeQ[DigitCount@#,0],#0[2#]+1,0]&

Попробуйте онлайн с помощью математики!


2
46 байтов: если [Tr [1 ^ Union @ IntegerDigits @ #] <10, # 0 [2 #] + 1,0] &
J42161217

Mathematica допускает анонимные рекурсивные функции. : o Спасибо!
полностью человек

2
38 байт: если [! FreeQ [DigitCount @ #, 0], # 0 [2 #] + 1,0] &
J42161217

ООО Спасибо! Кстати, `` можно использовать для кода, но начальные пробелы не допускаются. aбудет работать, но "а" не будет.
полностью человек

конечно! Кстати, вы можете использовать этот нижний колонтитул в Print/@f/@{617283945,2,66833,1234567890,100,42}
TIO

1

R , 74 байта

function(x){while(!all(0:9%in%el(strsplit(c(x,""),"")))){F=F+1;x=2*x};F*1}

Попробуйте онлайн!Обратите внимание, что R даст неправильный ответ f(2)из-за ограничений того, как язык хранит большие целые числа.

Объяснение: Для проверки pandigitality ввод приводится к символьному вектору путем соединения с пустой строкой, а затем разбивается на отдельные цифры. Затем мы проверяем, присутствуют ли все 0: 9 в результирующем векторе; если нет, мы увеличиваем счетчик, удваиваем ввод и повторяем.

Счетчик использует F, который инициализируется как ЛОЖЬ. Чтобы убедиться, что он приведен к числовому, мы умножаем его на единицу перед возвратом.


использование c(x,"")- el(strsplit(...))
Джузеппе

1

PowerShell , 70- 69 байт

for($n=[bigint]$args[0];([char[]]"$n"|group).count-le9;$n*=2){$i++}$i

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

(Почти вдвое дольше, чем ответ Python: - \)

Принимает ввод $args[0], преобразует его как [bigint], сохраняет его в $n. Входит в forцикл. На каждой итерации мы проверяем, имеет ли значение $number, преобразованное в строку, а затем в char-array, когда e Group-Objectвместе, .count -less than или equal to 9. Это означает, что единственный способ, которым он равен 10, - это наличие хотя бы одной цифры каждого числа 1234567890. Если да, мы выходим из цикла. Если нет, то мы $n*=2и продолжим. Каждую итерацию внутри цикла мы просто увеличиваем $i. Когда мы выходим из цикла, мы просто выводим$i .

Обратите внимание, что для ввода, подобного тому, 1234567890где каждая цифра уже учтена, это ничего не выдаст, что является ошибочным значением в PowerShell и эквивалентно тому, 0когда он приводится как [int]. Если это не так, мы можем просто поставить +перед выводом, $iчтобы явно привести его как целое число.

Спас байт благодаря Роланду Хиту.


Не могли бы вы использовать le9 вместо ne10? Я не знаком с PowerShell, но это может сэкономить байт.
Роланд Хит

@RolandHeath Действительно; хороший звонок. Благодарность!
AdmBorkBork



0

Perl, 43 + 1 байт

for$x(0..9){$_*=2,++$\,redo LINE if!/$x/}}{

Используя -pфлаг. Это основано на решении, предоставленном Xcali выше.


0

Swift 4 , 111 байт

func p(_ x:Int,_ c:Int=0)->Int{if !(String(Set(String(x)).sorted())=="0123456789"){return p(x*2,c+1)};return c}

Примечание: не будет работать для х = 2 из-за переполнения.

Пояснение - Ввод x сначала вводится в строку. Затем Set () удаляет повторяющиеся символы. Затем он сортируется в соответствии с результатом. Если он не совпадает, x удваивается и счетчик увеличивается.


1
это не работает, потому что переменная составляет 64 бита. Там много других ответов с той же проблемой.
Нареш


Если вы считаете, что это должно быть разрешено, доведите это до ОП. Это может быть обычной практикой, но ОП специально не разрешает это, и
Пост Рок Гарф Хантер

1
@FunkyComputerMan на самом деле, я разрешил ответы, которые не могут обрабатывать числа вне границ языка, но Шегги, кажется, удалил комментарий, спрашивая об этом. Этот ответ в порядке.
Caird Coneheringaahing

0

Рубин, 46 45 39 38 байт

def f n;n.digits.uniq[9]?0:1+f(n*2)end

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

Обновления:

  1. -1, используя def f n;вместо def f(n);.
  2. -6 с использованием …[9]вместо….size==10
  3. -1 путем удаления точки с запятой

0

Japt , 15 байт

LÆ*2pXÃbì_â Ê¥A

Попытайся


объяснение

Неявный ввод целого числа U.

LÆ    Ã

Создайте массив целых чисел от и 0до 99каждого из них через функцию, где Xнаходится текущий элемент.

*2pX

Uумноженный на 2, возведенный в степень X.

b

Получить индекс первого элемента, который возвращает true при передаче через следующую функцию.

ì_â

Разбить на массив цифр и удалить дубликаты.

Ê¥A

Получите длину массива и проверьте равенство с 10.


Альтернатива, 15 байт

@*2pX)ìâ sÊ¥A}a

Попытайся


объяснение

Неявный ввод целого числа U.

@            }a

Начиная с 0, верните первое число, которое возвращает true, когда передано через следующую функцию, с Xтекущим числом.

*2pX)

Как и выше, умножьте Uна 2 до степени X.

ìâ

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

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

¥A

Проверьте на равенство с 10.


0

QBIC , 48 байтов, nc

{q=1[z|q=q*instr(!:$,!a-1$)]~q>0|_Xp\p=p+1┘b=b*2

Это должно работать, в теории. Однако на практике это терпит неудачу, потому что QBasic преобразует десятизначные числа (по крайней мере, необходимые для получения всех цифр) в научную запись ... Я пометил его как неконкурентный из-за этого.

объяснение

{             DO ad infinitum
q=1           set q to 1
[z|           FOR a = 1 to 10
q=q*instr     multiply q by the position
(!:$             - in 'b' (read from cmd line at start) cast to string (! ... $)
,!a-1$)          - of the number a-1 [0-9] cast to string
]             NEXT
~q>0          IF any character was not found, instr gave a 0. If q != 0 all digits were present
|_Xp          THEN quit, printing  p (is 0 at start)
\p=p+1        ELSE increase step counter p
┘b=b*2        and double 'b'

0

GNU dc, 61 байт

Ввод копируется с вершины стека (который в противном случае должен быть пустым); вывод помещается на вершину стека.

[I~1r:ad0<s]ss[d1+r;a1=p]sp[d2*lfx]sh[0Sadlsxlpx11!=h]dsfxz1-

объяснение

Мы используем переменную массива a, сохраняя 1 в a[d]случае, если dприсутствует цифра , в противном случае возвращаемся к 0. Мы используем расширение GNU, ~чтобы получить частное и остаток в одной команде.

# populate a[0-9] from the digits
[I~1r:ad0<s]ss

# check pandigit
# return 1 more than lowest unset element of a[]
# start with stack=0
[d1+r;a1=p]sp

# Test for pandigit; double and repeat if needed
[dd+lfx]sh
[0Sadlsxlpx11!=h]dsfx

# We left one value on the stack for each doubling, plus the original
z1-

В качестве бонуса, это будет работать в произвольных числовых базах (не только десятичных): просто установите входной радиус как требуется (константа 11в определенииf будет считываться с использованием этой числовой базы, поэтому она автоматически корректна).

Тестовое задание

for i in 617283945 2 66833 1234567890 100 42
do
    printf '%s => ' $i
    dc -e $i \
       -e '[I~1r:ad0<s]ss[d1+r;a1=p]sp[dd+lfx]sh[0Sadlsxlpx11!=h]dsfxz1-' \
       -e p
done
617283945 => 1
2 => 67
66833 => 44
1234567890 => 0
100 => 51
42 => 55


0

q / kdb + , 33 байта

Решение:

(#)1_{x*2 1 min!:[10]in 10 vs x}\

Примеры:

q)(#)1_{x*2 1 min!:[10]in 10 vs x}\[100]
51
q)(#)1_{x*2 1 min!:[10]in 10 vs x}\[1234567890]
0
q)(#)1_{x*2 1 min!:[10]in 10 vs x}\[42]
55

Объяснение:

Все байты находятся в равенстве, возможно, удастся немного ускорить этот процесс. Использует scanнаречие q :

count 1_{x*2 1 min til[10] in 10 vs x}\ / ungolfed solution
        {                            }\ / scan over this lambda until it yields same result
                              10 vs x   / convert to base 10
                           in           / left list in right list, returns boolean list
                   til[10]              / range 0..9
               min                      / return the minimum of the list, 0 or 1
           2 1                          / list (2;1) indexed into with 0 or 1
         x*                             / return x multiplied by either 2 or 1
      1_                                / 1 drop, drop one element from front of list
count                                   / count the length of the list

Примечания:

Если мы перейдем к kприглашению, у нас будет 25-байтовое решение. Преобразует число в список символов:

q)\
  #1_{x*2 1@&/($!10)in$$x}\[100]
51
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.