Знайдіть сортувальні роки


26

2013 рік мав цікаву властивість: цифри є послідовними при сортуванні (0123). Назвемо цей тип числа сортувальним числом: невід’ємне ціле число, чисельність базових 10 цифр є послідовним після сортування. На жаль, це не повториться до 2031 року, а після цього, не до 2103. Вашим завданням є написати програму або функцію, яка, отримавши невід'ємне ціле число за допомогою будь-якого стандартного методу, виводить або повертає наступне сортоване число.

Правила

  • Вхід і вихід повинні бути в базі 10.
  • Вихід може бути у будь-якому розумному форматі (числовий літерал, рядковий літерал, масив з одним пунктом, ...).
  • Ваш код повинен створити належний вихід протягом 1 хвилини для всіх входів до 98764.

Тестові справи

    0 -> 1
    1 -> 2
    9 -> 10
   10 -> 12
   11 -> 12
   99 -> 102
  233 -> 234
  234 -> 243
  243 -> 312
 2016 -> 2031
 2031 -> 2103
 2103 -> 2130
 2130 -> 2134
 2134 -> 2143
 9876 -> 10234
98764 -> 98765

Номери сортування формують A215014 . Список усіх записів до 98765 можна знайти тут .

Оцінка балів

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


Що ви маєте на увазі під роботою ? Чи гаразд, якщо це займе дуже довго?
Денніс

@Dennis Він повинен закінчити за 1 хвилину на всі входи до 98764. Це було з’ясовано у публікації.
ETHproductions

@ETHproductions Чи має взагалі підтримувати більші входи?
Мартін Ендер

@MartinEnder Ні, хоча я очікую, що більшість (якщо не всі) рішення будуть. Чи повинна вимога бути вищою?
ETHproductions

@ETHproductions Я не думаю, що я просто хотів переконатися.
Мартін Ендер

Відповіді:


9

Python 2 , 61 байт

f=lambda n:-~n*(`sorted(`n+1`)`[2::5]in'0123456789')or f(n+1)

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


1
Я хочу '0123456789'бути чимось подібним 1./81, але це не зовсім спрацьовує.
xnor

Найкраще ви отримуєте те, 1./81.0000001що все-таки не працює належним чином і довше
Alfie Goodacre

@AlfieGoodacre Ви могли б зробити краще, 1./81-1e-10але це все-таки 10 байт, і вам доведеться все-таки обрізати.
Мартін Ендер

7

Желе , 11 10 9 байт

⁵ḶwṢ
‘Ç1#

Повертає однотонний масив. Спробуйте в Інтернеті!

Як це працює

‘Ç1#  Main link. Argument: n

‘     Increment; yield n+1.
 Ç1#  Apply the helper link to k = n+1, n+2, n+3, ... until one of them maps to a
      truthy value. Yield a singleton array containing that value of k.

⁵ḶwṢ  Helper link. Argument: k

⁵     Set the return value to 10.
 Ḷ    Unlength; yield [0, ..., 9].
   Ṣ  Sort; yield the sorted array of k's decimal digits.
  w   Window-index; yield the 1-based index(truthy) of the digit array in
      [0, ..., 9], 0 (falsy) if not found.

6

MATL , 8 байт

`QtVSdqa

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

Пояснення

`     % Do...while
  Q   %   Add 1. Takes input (implicit) in the first iteration
  t   %   Duplicate
  V   %   Convert to string. This gives an array of chars (same as a string)
      %   representing the digits
  S   %   Sort
  d   %   Consecutive differences between the chars (automatically converted
      %   to ASCII codes)
  q   %   Subtract 1. This gives an array where consecutive differences equal 
      %   to 1 are converted to 0, and the rest give a nonzero result
  a   %   True if any value is nonzero. This is the loop condition: if true
      %   (which means at least one consecutive difference was not 1), go on
      %   with the next iteration. Else exit loop
      % End do...while (implicit)
      % Display (implicit)

5

JavaScript (ES6), 64 54 байти

Збережено величезні 10 байт, завдяки Нілу

f=n=>[...++n+''].sort().some((v,i,a)=>v-i-a[0])?f(n):n

Тестові справи


2
Ви можете зберегти 2 байти від своєї початкової відповіді, зазначивши, що третім параметром mapзворотного виклику є сам масив, але ви можете продовжувати робити це набагато краще:f=n=>[...++n+''].sort().some((v,i,a)=>v-i-a[0])?f(n):n
Ніл


4

PowerShell v2 +, 71 68 67 байт

param($n)do{$n++}until(-join(0..9)-match-join([char[]]"$n"|sort))$n

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

Ітераційне рішення, яке працює майже миттєво на моїй машині.

PS C:\Tools\Scripts\golfing> measure-command {.\find-the-sortable-years.ps1 98764} | fl totalseconds

TotalSeconds : 0.0487127

Так, це do/ untilцикл у коді-гольф. Жаль не шкода. По суті, ми робимо циклічне вгору від нашого введення, $nпоки не будуть $n|sortвиправлені регулярні вирази -matchпроти 0123456789. Потім розміщуємо $nна конвеєрі, а вихід неявний.

Збережено байт, зрозумівши, що -join(0..9)на один байт коротший, ніж буквальний рядок 0123456789.


3

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

#+1//.x_/;!Differences@Sort@IntegerDigits@x~MatchQ~{1...}:>x+1&

Замінює #+1наступне значення до тих пір, як Differences@Sort@IntegerDigits@x~MatchQ~{1...}значення false, що є умовою сортування поточного значення.

Ось ще одна цікава ідея, яка, на жаль, виявилася занадто довго:

FirstCase[FromDigits/@Union@@Permutations/@Join@@Array[Range,{9,10},0],x_/;x>#]&

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

Ще кілька ідей, які не виявилися коротшими, ніж перша спроба:

#+1//.x_/;Array[Range,{9,10},0]~FreeQ~Sort@IntegerDigits@x:>x+1&
#+1//.x_/;Subsequences@Range[0,9]~FreeQ~Sort@IntegerDigits@x:>x+1&
#+1//.x_/;0~Range~9~FreeQ~{___,##&@@Sort@IntegerDigits@x,___}:>x+1&

3

PHP, 105 103 89 байт

Нова версія 89 байт завдяки Титу:

for(;!$p;){$t=str_split($n=++$argv[1]);sort($t);$p=strstr('0123456789',join($t));}echo$n;

Використання:

php -r "for(;!$p;){$t=str_split($n=++$argv[1]);sort($t);$p=strstr('0123456789',join($t));}echo$n;" 9000

Попередня версія 103 байтів завдяки Xanderhall:

<?for($p=0;!$p;){$t=str_split($n=++$_GET[n]);sort($t);$p=strstr('0123456789',implode($t));}echo "$n\n";

Попередня версія 105 байт:

<?for($n=$_GET[n]+1;;$n++){$t=str_split($n);sort($t);if(strstr('0123456789',implode($t))){echo$n;exit;}}

Використання: sortable-years.php?n=9000виходи 9678.

Неперевершена версія з тестовими кейсами:

$test = array(0,1,9,10,11,99,233,234,243,2016,2031,2103,2130,2134,9876,98764);

foreach ($test as $argv[1]) {
    for(;!$p;){
        $t=str_split($n=++$argv[1]);
        sort($t);
        $p=strstr('0123456789',join($t));
    }
    echo "$n\n"; // add newline for testing
    $p=false; // reset $p for testing
}

Output:
1
2
10
12
12
102
234
243
312
2031
2103
2130
2134
2143
10234
98765

Перевірте онлайн! (Нова версія 89 байт)

Перевірте онлайн! (Попередня версія 103 байти)

Перевірте онлайн! (Попередня версія 105 байт)

Час виконання може бути <= 1 секунда для всіх тестових випадків.



@Xanderhall дякую за ваші вдосконалення. Насправді я намагався знайти спосіб зняти це break( exitна версії для гольфу), ви знайшли це! Чудово.
Маріо

Посилання, яке я опублікував, було лише кодом, щоб дати вам уявлення про те, як його вдосконалити, це не повністю гольф XD
Xanderhall

$i=0є непотрібним (-4). joinє псевдонімом для implode(-3). echo$nдостатній вихід (-5). $argv[1]замість $_GET[n]дозволу, -rякий дозволяє опустити <?тег (-2).
Тит

@Titus велике спасибі за ваші чудові поради щодо гольфу, у мене ще багато чого, щоб дізнатися про це, і я також повинен звернути більше уваги на деякі деталі, які я сумую ... Я ще не знав про joinпсевдонім implode! Щодо php -rпараметра, який я використовував раніше, але останнім часом я його не використовую, оскільки (не знаю чому) іноді я не можу змусити його працювати належним чином у деяких випадках.
Маріо

2

Perl 6 , 49 байт

{first {$/eqv($/=.comb.sort).minmax.list},$_^..*}

Пояснення

{

  first

  {

    $/             # sorted list from later

    eqv            # is it equivalent

    (

      $/           # store in match variable ( doesn't need to be declared )
      =
      .comb.sort   # sorted list of digits from currently tested value

    ).minmax       # the Range of digits
            .list  # flattened to a list
  },

  $_  ^..  *       # Range starting just after input

}

Тест:

# give it a lexical name for clarity
my &code = {first {$/eqv($/=.comb.sort).minmax.list},$_^..*}

my @all = 'sortable.txt'.IO.lines;

my @gen = code(-1), &code ... ( * >= 98765 );

say @all eqv @gen; # True

say now - INIT now; # 16.3602371

2

C #, 153 130 101 байт ( 122 99 83 без урахування декларацій простору імен)

using System.Linq;n=>{while(!"0123456789".Contains(string.Concat((++n+"").OrderBy(x=>x))));return n;}

-23 байти завдяки pinkfloydx33

ще -29 завдяки Link Ng (я дійсно повинен був знати, що мені не потрібно перетворювати його в масив)

Чортове перетворення.

(Додано бонус, це дивно швидко)


Вам не потрібно робити рядки, використовувати $"{n}".ToCharArray()або (""+n).ToCharArray()і вам не потрібні дужки через деякий час: while(!s.Contains...)n++;або ще краще об'єднати їх і залишити порожнє тіло циклу: while(!s.Contains(.....$"{n++}".ToCharArray()....);return n; оголосити s var s="... "або видалити його повністю:while(!"0123456789".Contains(...
pinkfloydx33

Я думаю, ви також можете видалити перший n++і замість цього комбінувати його з вищезазначеним і зробити$"{++n}".ToCharArray()
pinkfloydx33

@ pinkfloydx33 Я додав більшість запропонованих вами змін, якщо не всі!
Alfie Goodacre

1
Видаліть use System;і використовуйте stringзамість String11 байт. Використовуйте string.Concatзамість string.Joinта зберігайте лише 2-й параметр на 1 байт. Змініть ""+ ++nна ++n+""1 байт. Додано вам як вправу: ще 14 байт можна видалити.
Посилання Ng

@LinkNg зміни були внесені - я відчуваю себе дурнем для масиву xD
Alfie Goodacre

1

Befunge , 117 байт

&>1+0v
9`#v_>:9+0\4p1+:
1:$<v
0g1+>00p:55+%9+1\4p55+/:!#v_0
v+*g09:<".........." 9p09 <
>:00g-v^<
-9:p09_v|
$v@._<$<>

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

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

Детальне пояснення

&>1+                              Read the year and increment it.

    0v                            The "array" is initialized with zeros prior
9`#v_>:9+0\4p1+:                     to processing each year.

1:$<v                             For every digit, set the corresponding array index
0g1+>00p:55+%9+1\4p55+/:!#v_0       to one, and increment the year length counter.

                      p09 <       Initialise the sequence counter to zero.
                     9            Push a marker onto the stack.
        ".........."              Push the values from the array onto the stack.

v+*g09:<                          Increment the sequence counter for every 1 in the
>:00g-v^<                           array and reset it on every 0. Break if it equals
-9:p09_v|                           the year length or we encounter the end marker.

  @._<$<                          If we have a match, clear the stack and output the year.
$v      >                         If we've reached the marker, drop it try the next year.

1

Рубі, 51 байт

->n{n+=1 until'0123456789'[n.to_s.chars.sort*''];n}

1

Python 2, 68 байт

n=input()+1
while''.join(sorted(`n`))not in'0123456789':n+=1
print n

Добре побитий @Dennis, але все-таки просто розміщений як альтернативний метод.


1

C #, 127 байт

using System.Linq;n=>{char[]s;while((s=(++n+"").OrderBy(x=>x).ToArray()).Select((x,i)=>i>0&&x-s[i-1]!=1).Any(x=>x));return n;};

Побийте поточне подання на C # на 3 байти: p Відбитий вже
я знаю, що ця відповідь буде легко відбита ...
repl.it demo

Безумовно

n=>
{
    char[] s;
    while((
        // Store char array in variable to be referenced in Select()
        // Increment n and cast to string
        s=(++n+"")
            // Sort ascending, to array
            .OrderBy(x=>x)
            .ToArray())
        // Convert char to true if it's not at position 0,
        // and it is not 1 greater than the previous char
        .Select((x,i)=>i>0&&x-s[i-1]!=1)
        // All false: n is sortable
        // Any true: n is not sortable
        .Any(x=>x))
    // while loop body is empty
    ;
    return n;
};


1

Пітон 2, 118 117 114 108 байт

x,s=input()+1,sorted
while[j for i,j in enumerate(s(str(x))[1:])if int(s(str(x))[i])+1!=int(j)]:x+=1
print x

Редагувати:

-1 байт завдяки @ Gábor Fekete

-6 байт завдяки @Zachary T


Ви можете зберегти 1 байт, вибравши sortedфункцію.
Габор Фекете

Ви не можете зберегти кілька байт, перейшовши на python 2?
Zacharý

Так, я міг, дякую, я про це не думав.
sonrad10

1

PHP, 90 89 88 байт

зовсім інший підхід:

while(array_unique($a=str_split($n=++$argv[1]))!=$a|max($a)-min($a)-count($a)+1);echo$n;

Бігайте з -r.

зламатися

while(
    array_unique(           // 3. unique values
        $a=str_split(       // 2. split to digits
            $n=++$argv[1]   // 1. increase number
        )
    )
    !=$a                    // 4. repeat while unique digits differ from original digits
    |                       // or
        max($a)-min($a)     // digit range
        -count($a)+1        // differs from count-1
    );
echo$n;                 // print result

0

Clojure, 104 96 91 байт

Довгі назви методів не роблять це настільки коротким ... Принаймні, map-indexedі робіть -основні розрахунки акуратно.

Редагувати 1 : Акуратно, я забув також =може приймати декілька аргументів, тому мені не потрібно перевіряти, чи є кількість різних значень 1.

Правка 2 : Не потрібно бігати (sort(seq(str %))), (sort(str %))працює однаково добре.

(fn[i](first(filter #(apply =(map-indexed -(map int(sort(str %)))))(rest(iterate inc i)))))

Безголівки:

(defn f [i]
  (let [is-sorted? #(= 1 (->> % str sort (map int) (map-indexed -) set count))]
    (->> i (iterate inc) rest (filter is-sorted?) first)))

0

R, 87 байт

f=function(x)`if`(all(diff(sort(as.double(el(strsplit(c(x+1,""),"")))))==1),x+1,f(x+1))

Як звичайно, якщо мова йде про розбиття чисел на цифри, R не має звичного способу зробити це. Отже, нам потрібно примусити ввести символ, розділити його на векторний символ і згодом перетворити назад в будь-який числовий тип.

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

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