Trova gli anni ordinabili


26

L'anno 2013 ha avuto una proprietà interessante: le cifre sono consecutive se ordinate (0123). Chiamiamo questo tipo di numero un numero ordinabile: un numero intero non negativo le cui cifre in base 10 sono consecutive dopo l'ordinamento. Sfortunatamente, questo non accadrà più fino al 2031, e successivamente, non fino al 2103. La tua sfida è scrivere un programma o una funzione che, quando viene dato un numero intero non negativo attraverso un metodo standard, emetta o restituisce il prossimo numero ordinabile.

Regole

  • Ingresso e uscita devono essere nella base 10.
  • L'output può essere in qualsiasi formato ragionevole (letterale numero, letterale stringa, array a singolo elemento, ...).
  • Il codice deve produrre l'output corretto entro 1 minuto per tutti gli input fino a 98764.

Casi test

    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

I numeri ordinabili formano A215014 . Un elenco di tutte le voci fino a 98765 è disponibile qui .

punteggio

Questo è , quindi vince il codice più breve in byte.


Cosa intendi per lavoro ? Va bene se ci vuole molto tempo?
Dennis,

@Dennis Deve finire con 1 minuto per tutti gli input fino a 98764. Questo è stato chiarito nel post.
ETHproductions

@ETHproductions Deve supportare input più grandi?
Martin Ender,

@MartinEnder No, anche se mi aspetto che la maggior parte delle soluzioni (se non tutte). Il requisito dovrebbe essere più elevato?
ETHproductions

@ETHproductions Non credo, volevo solo esserne sicuro.
Martin Ender,

Risposte:


9

Python 2 , 61 byte

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

Provalo online!


1
Voglio '0123456789'essere qualcosa del genere 1./81, ma non funziona del tutto.
xnor

Il meglio che stai ottenendo è 1./81.0000001che ancora non funzionerebbe correttamente ed è più lungo
Alfie Goodacre,

@AlfieGoodacre Potresti fare di meglio 1./81-1e-10ma sono ancora 10 byte e dovresti comunque troncarlo .
Martin Ender,

7

Gelatina , 11 10 9 byte

⁵ḶwṢ
‘Ç1#

Restituisce un array singleton. Provalo online!

Come funziona

‘Ç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 byte

`QtVSdqa

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

`     % 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 byte

Risparmiato un enorme 10 byte, grazie a Neil

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

Casi test


2
Puoi salvare 2 byte dalla tua risposta originale notando che il terzo parametro del mapcallback è l'array stesso, ma puoi continuare a fare molto meglio:f=n=>[...++n+''].sort().some((v,i,a)=>v-i-a[0])?f(n):n
Neil


4

PowerShell v2 +, 71 68 67 byte

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

Provalo online!

Una soluzione iterativa che funziona praticamente istantaneamente sulla mia macchina.

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

TotalSeconds : 0.0487127

Sì, questo è un do/ untilloop in un code-golf. Scusa, non scusa Fondamentalmente abbiamo anello verso l'alto del nostro ingresso $nfino $n|sortndr regex -matches contro 0123456789. Quindi posizioniamo $nsulla pipeline e l'output è implicito.

Ho salvato un byte realizzando che -join(0..9)è un byte più corto della stringa letterale 0123456789.


3

Mathematica, 63 byte

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

Sostituisce #+1con il valore successivo fintanto che Differences@Sort@IntegerDigits@x~MatchQ~{1...}è falso, che è la condizione che il valore corrente sia ordinabile.

Ecco un'altra idea divertente, che purtroppo è finita troppo a lungo:

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

In questo, sto generando prima tutti gli anni ordinabili e poi seleziono il primo che è maggiore dell'input.

Alcune idee in più che non si sono rivelate più brevi del primo tentativo:

#+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 byte

Nuova versione da 89 byte grazie 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

Precedente 103 byte grazie a Xanderhall:

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

Versione precedente di 105 byte:

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

Utilizzo: sortable-years.php?n=9000uscite 9678.

Versione non golfata con casi di test:

$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

Test online! (Nuova versione da 89 byte)

Test online! (Versione precedente 103 byte)

Test online! (Versione precedente 105 byte)

Il tempo di esecuzione può essere <= 1 secondo per tutti i casi di test.



@Xanderhall grazie per i tuoi miglioramenti. In realtà stavo cercando di trovare un modo per portarlo via break( exitnella versione golfata), l'hai trovato! Grande.
Mario,

Il link che ho pubblicato era solo un codice per darti un'idea di come migliorarlo, non è completamente giocato a golf XD
Xanderhall

$i=0non è necessario (-4). joinè un alias per implode(-3). echo$nè sufficiente output (-5). $argv[1]invece di $_GET[n]consente -rche consente di omettere il <?tag (-2).
Tito

@Titus grazie mille per i tuoi fantastici consigli sul golf, ho ancora così tanto da imparare a riguardo, e devo anche prestare più attenzione ad alcuni dettagli che mi mancano ... Non sapevo ancora joincome alias di implode! Per quanto riguarda il php -rparametro, ho usato in passato ma ultimamente non lo sto usando perché (non so perché) a volte non riesco a farlo funzionare correttamente in alcuni casi.
Mario,

2

Perl 6 , 49 byte

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

Spiegazione

{

  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

}

Test:

# 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 byte ( 122 99 83 escluse le dichiarazioni dello spazio dei nomi)

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

-23 byte grazie a pinkfloydx33

un altro -29 grazie a Link Ng (avrei dovuto davvero sapere che non ho bisogno di convertirlo in un array)

Dannate conversioni.

(Aggiunto bonus questo è sorprendentemente veloce)


Non hai bisogno di stringhe, usare $"{n}".ToCharArray()o (""+n).ToCharArray()e non hai bisogno delle parentesi dopo il tempo: while(!s.Contains...)n++;o meglio ancora combinarle e lasciare un corpo del ciclo vuoto: while(!s.Contains(.....$"{n++}".ToCharArray()....);return n; dichiarare s con var s="... "o rimuoverlo completamente:while(!"0123456789".Contains(...
pinkfloydx33

Penso che puoi anche rimuovere il primo n++e invece combinarlo con il sopra e fare$"{++n}".ToCharArray()
pinkfloydx33

@ pinkfloydx33 Ho aggiunto la maggior parte delle modifiche che hai suggerito, se non tutte!
Alfie Goodacre,

1
Rimuovere use System;e utilizzare stringanziché Stringper 11 byte. Utilizzare string.Concatinvece di string.Joine mantenere solo il secondo parametro per 1 byte. Passare ""+ ++na ++n+""per 1 byte. Lasciato a te come esercizio: è possibile rimuovere altri 14 byte.
Link ng

Sono state apportate modifiche a @LinkNg - Mi sento uno sciocco per l'array xD
Alfie Goodacre,

1

Befunge , 117 byte

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

Provalo online!

Il modo in cui testiamo se un anno è ordinato creando un "array" (scritto nella stringa letterale alla riga cinque) e per ogni cifra dell'anno, impostiamo quell'indice nell'array su 1. Una volta che tutte le cifre sono state elaborato, contiamo quanti 1 ci sono in sequenza e se quel conteggio è uguale alla lunghezza dell'anno possiamo supporre che l'anno sia ordinato.

Spiegazione dettagliata

&>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

Rubino, 51 byte

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

1

Python 2, 68 byte

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

Ben battuto da @Dennis ma appena pubblicato come metodo alternativo.


1

C #, 127 byte

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

Batti l'attuale invio in C # di 3 byte: p Già respinto
So che questa risposta sarà respinta 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;
};


1

Python 2, 118 117 114 108 byte

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

MODIFICARE:

-1 Byte grazie a @ Gábor Fekete

-6 byte grazie a @Zachary T


È possibile salvare 1 byte aliasando la sortedfunzione.
Gábor Fekete,

Non riesci a salvare alcuni byte convertendoli in Python 2?
Zacharý,

Sì, grazie, non ci avevo pensato.
sonrad10,

1

PHP, 90 89 88 byte

un approccio completamente diverso:

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

Corri con -r.

abbattersi

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 byte

I nomi lunghi dei metodi non lo rendono così breve ... Almeno map-indexede -fai i calcoli principali in modo accurato.

Modifica 1 : pulito, ho dimenticato anche di =prendere più argomenti, quindi non ho bisogno di controllare se il conteggio di valori distinti è 1.

Modifica 2 : non è necessario eseguirlo (sort(seq(str %))), (sort(str %))funziona ugualmente bene.

(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)))

0

R, 87 byte

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

Come al solito quando si tratta di dividere i numeri in cifre, R non ha un modo nativo per farlo. Di conseguenza, dobbiamo forzare l'input in un carattere, dividerlo in un vettore di carattere e successivamente riconvertirlo in qualsiasi tipo numerico.

Provalo online

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.