Encontre os anos classificáveis

26

O ano de 2013 teve uma propriedade interessante: os dígitos são consecutivos quando classificados (0123). Vamos chamar esse tipo de número de número classificável: um número inteiro não negativo cujos dígitos da base 10 são consecutivos após a classificação. Infelizmente, isso não acontecerá novamente até 2031, e depois disso, não até 2103. Seu desafio é escrever um programa ou função que, ao receber um número inteiro não negativo por meio de qualquer método padrão, produza ou retorne o próximo número classificável.

Regras

  • A entrada e a saída devem estar na base 10.
  • A saída pode estar em qualquer formato razoável (literal de número, literal de cadeia, matriz de item único, ...).
  • Seu código deve produzir a saída adequada em 1 minuto para todas as entradas até 98764.

Casos de teste

    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

Os números classificáveis ​​formam A215014 . Uma lista de todas as entradas até 98765 pode ser encontrada aqui .

Pontuação

Isso é , então o código mais curto em bytes vence.

ETHproductions
fonte
O que você quer dizer com trabalho ? Tudo bem se demorar muito?
Dennis
@Dennis Ele deve terminar com 1 minuto para todas as entradas até 98764. Isso foi esclarecido na publicação.
ETHproductions
@ETHproductions Ele precisa suportar entradas maiores?
Martin Ender
@ MartinEnder Não, embora eu espere que a maioria (se não todas) as soluções o façam. O requisito deve ser maior?
ETHproductions
@ETHproductions Acho que não, só queria ter certeza.
22816 Martin Ender

Respostas:

9

Python 2 , 61 bytes

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

Experimente online!

Dennis
fonte
1
Eu quero '0123456789'ser algo como 1./81, mas não funciona muito bem.
Xnor
Melhor que você está recebendo é 1./81.0000001que ainda não o faria corretamente trabalho e é mais longo
Alfie Goodacre
@AlfieGoodacre Você poderia fazer melhor, 1./81-1e-10mas ainda tem 10 bytes e ainda precisará truncá-lo.
Martin Ender
7

Geléia , 11 10 9 bytes

⁵ḶwṢ
‘Ç1#

Retorna uma matriz singleton. Experimente online!

Como funciona

‘Ç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.
Dennis
fonte
6

MATL , 8 bytes

`QtVSdqa

Experimente online! Ou verifique todos os casos de teste .

Explicação

`     % 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)
Luis Mendo
fonte
5

JavaScript (ES6), 64 54 bytes

Economizou 10 bytes em massa, graças a Neil

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

Casos de teste

Arnauld
fonte
2
Você pode salvar 2 bytes da sua resposta original, observando que o terceiro parâmetro para o mapretorno de chamada é a própria matriz, mas você pode fazer muito melhor:f=n=>[...++n+''].sort().some((v,i,a)=>v-i-a[0])?f(n):n
Neil
4

PowerShell v2 +, 71 68 67 bytes

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

Experimente online!

Uma solução iterativa que roda praticamente instantaneamente na minha máquina.

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

TotalSeconds : 0.0487127

Sim, isso é um loop do/ untilem um código-golfe. Desculpe, não desculpe. Basicamente, fazemos um loop para cima a partir de nossa entrada $naté que os $n|sortregex sejam -matchcontra 0123456789. Em seguida, colocamos $nno pipeline e a produção está implícita.

Salva um byte ao perceber que -join(0..9)é um byte menor que a string literal 0123456789.

AdmBorkBork
fonte
3

Mathematica, 63 bytes

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

Substitui #+1pelo próximo valor, desde que Differences@Sort@IntegerDigits@x~MatchQ~{1...}seja falso, que é a condição em que o valor atual é classificável.

Aqui está outra idéia divertida, que infelizmente acabou sendo longa demais:

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

Neste, estou gerando todos os anos classificáveis ​​primeiro e depois seleciono o primeiro que é maior que a entrada.

Mais algumas idéias que não foram mais curtas que a primeira tentativa:

#+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&
Martin Ender
fonte
3

PHP, 105 103 89 bytes

Nova versão de 89 bytes graças a Titus:

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

Uso:

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

Versão anterior de 103 bytes graças a Xanderhall:

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

Versão anterior de 105 bytes:

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

Uso: sortable-years.php?n=9000saídas 9678.

Versão ungolfed com casos de teste:

$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

Teste online! (Nova versão de 89 bytes)

Teste online! (Versão anterior de 103 bytes)

Teste online! (Versão anterior de 105 bytes)

Tempo de execução talvez <= 1 segundo para todos os casos de teste.

Mario
fonte
Fiz algumas melhorias
Xanderhall 15/12/16
@Xanderhall, obrigado por suas melhorias. Na verdade, eu estava tentando encontrar uma maneira de tirar isso break( exitna versão de golfe), você encontrou! Ótimo.
Mario
O link que eu publiquei era apenas um código para lhe dar uma idéia de como melhorá-lo, não é totalmente XD
Xanderhall
$i=0é desnecessário (-4). joiné um alias para implode(-3). echo$né saída suficiente (-5). $argv[1]em vez de $_GET[n]allow, o -rque permite omitir a <?tag (-2).
Titus
@Titus, muito obrigado por suas ótimas dicas de golfe, ainda tenho muito a aprender sobre isso e também preciso prestar mais atenção em alguns detalhes que sinto falta ... ainda não sabia joincomo pseudônimo implode! Sobre o php -rparâmetro que usei no passado, mas ultimamente não o uso porque (não sei por que) às vezes não consigo fazê-lo funcionar corretamente em alguns casos.
Mario
2

Perl 6 , 49 bytes

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

Explicação

{

  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

}

Teste:

# 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
Brad Gilbert b2gills
fonte
2

C #, 153 130 101 bytes ( 122 99 83 excluindo declarações de espaço para nome)

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

-23 bytes graças a pinkfloydx33

outro -29 graças ao Link Ng (eu realmente deveria saber que não preciso convertê-lo em uma matriz)

Malditas conversões.

(Bônus adicionado, isso é surpreendentemente rápido)

Alfie Goodacre
fonte
Você não precisa amarrar, usar $"{n}".ToCharArray()ou (""+n).ToCharArray()e não precisa dos colchetes depois de um tempo: while(!s.Contains...)n++;ou melhor ainda, combiná-los e deixar um corpo de loop vazio: while(!s.Contains(.....$"{n++}".ToCharArray()....);return n; declare s com var s="... "ou remova-o completamente:while(!"0123456789".Contains(...
pinkfloydx33
Acho que você também pode remover o primeiro n++e, em vez combiná-lo com o acima e fazer$"{++n}".ToCharArray()
pinkfloydx33
@ pinkfloydx33 Adicionei a maioria das alterações que você sugeriu, se não todas!
Alfie Goodacre
1
Remova use System;e use em stringvez de Stringpor 11 bytes. Use em string.Concatvez de string.Joine mantenha apenas o segundo parâmetro para 1 byte. Mude ""+ ++npara ++n+""para 1 byte. Deixado para você como exercício: mais 14 bytes podem ser removidos.
Fazer a ligação Ng
Mudanças @LinkNg foram feitas - Eu me sinto como um tolo para o xD variedade
Alfie Goodacre
1

Anterior , 117 bytes

&>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@._<$<>

Experimente online!

A maneira como testamos se um ano é classificado é criando uma "matriz" (escrita na cadeia literal na linha cinco) e para cada dígito do ano, definimos esse índice na matriz como 1. Depois que todos os dígitos tiverem sido processado, contamos quantos 1s existem em sequência e, se essa contagem for igual à duração do ano, podemos assumir que o ano está classificado.

Explicação detalhada

&>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.
James Holderness
fonte
1

Ruby, 51 bytes

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

Python 2, 68 bytes

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

Bem derrotado por @Dennis, mas apenas postado como um método alternativo de qualquer maneira.

ElPedro
fonte
1

C #, 127 bytes

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;};

Bata a submissão atual do C # em 3 bytes: p
vencido, eu sei que essa resposta será vencida facilmente ...
repl.it demo

Ungolfed

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;
};
Ng do link
fonte
1

05AB1E , 10 9 bytes

-1 graças a Emigna.

[>D{žhså#

Experimente online!

Nova descrição chegando quando eu tiver tempo.

Urna de polvo mágico
fonte
2
[>D{žhså#por 9 bytes.
Emigna
1

Python 2, 118 117 114 108 Bytes

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

EDITAR:

-1 Byte graças a @ Gábor Fekete

-6 Bytes graças a @Zachary T

sonrad10
fonte
Você pode economizar 1 byte alterando a sortedfunção.
Gábor Fekete
Você não pode salvar alguns bytes convertendo para python 2?
Zachary
Sim, eu poderia, obrigado, eu não tinha pensado nisso.
sonrad10
1

PHP, 90 89 88 bytes

uma abordagem completamente diferente:

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

Corra com -r.

demolir

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
Titus
fonte
0

Clojure, 104 96 91 bytes

Nomes de métodos longos não tornam isso tão curto ... Pelo menos, map-indexede os -principais cálculos são feitos de maneira organizada.

Edit 1 : puro, eu esqueci também =pode levar vários argumentos, então eu não preciso verificar se a contagem de valores distintos é 1.

Edit 2 : Não há necessidade de executar (sort(seq(str %))), (sort(str %))funciona igualmente bem.

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

Ungolfed:

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

R, 87 bytes

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

Como de costume, quando se trata de dividir números em dígitos, R não possui uma maneira nativa de fazer isso. Conseqüentemente, temos que coagir a entrada em um caractere, dividir em um vetor de caractere e, posteriormente, converter novamente em qualquer tipo numérico.

Experimente online

Billywob
fonte