Genera numeri Dennis


69

Questa sfida è un tributo all'utente Dennis PPCG per aver vinto la parte dei ladri di The Programming Language Quiz .

Guardando la pagina del profilo PPCG di Dennis possiamo vedere alcune cose piuttosto impressionanti:

Profilo di Dennis

Attualmente ha oltre sessantotto mila reputazione, il che lo rende il secondo in classifica generale , superando il terzo posto di quasi trentamila. Di recente ha vinto le nostre elezioni per un nuovo moderatore e ha ottenuto un nuovo brillante diamante accanto al suo nome. Ma personalmente ritengo che la parte più interessante di Dennis sia il suo numero ID utente PPCG: 12012.

A prima vista 12012sembra quasi un palindromo , un numero che legge lo stesso quando è invertito, ma è un po 'fuori. Può diventare il palindromo 21012se scambiamo le posizioni del primo 1e 2, e può diventare il palindromo 12021se scambiamo l'ultimo 1e 2. Inoltre, in base alla convenzione, gli zero iniziali in un numero non vengono scritti, scambiando il primo 1e i 0risultati 02112o piuttosto 2112un altro palindromo.

Definiamo un numero di Dennis come un numero intero positivo che non è palindromico stesso ma può essere trasformato in un palindromo scambiando le posizioni di almeno una coppia di due cifre. L' ordine di un numero di Dennis è il numero di coppie distinte di cifre che possono essere scambiate per creare un palindromo (non necessariamente distinto).

Quindi l'ordine di 12012è 3 da 3 distinte coppie di sue cifre ( 12012, , ) può essere scambiato intorno a produrre palindromi. sembra essere il numero 3 Dennis più piccolo ordine.120121201212012

10è il numero Dennis più piccolo e ha l'ordine 1 perché il cambio intorno 1e 001aka 1che è un palindromo.

Gli zeri iniziali immaginari di un numero non contano come cifre commutabili. Ad esempio, la modifica 8908di 08908e scambiare le prime due cifre per ottenere il palindromo 80908non è valido. 8908non è un numero Dennis.

Si potrebbe dire che i numeri non Dennis hanno un ordine 0.

Sfida

Scrivi un programma o una funzione che accetta un numero intero positivo N e stampa o restituisce l'ennesimo numero Dennis più piccolo insieme al suo ordine in un formato ragionevole come 12012 3o (12012, 3).

Ad esempio, 12012è il 774 ° numero Dennis, quindi se 774è l'input per il tuo programma, l'output dovrebbe essere qualcosa di simile 12012 3. (Curiosamente, 774 è un altro numero di Dennis.)

Vince il codice più breve in byte.

Ecco i primi 20 numeri di Dennis e i loro ordini di riferimento:

N       Dennis  Order
1       10      1
2       20      1
3       30      1
4       40      1
5       50      1
6       60      1
7       70      1
8       80      1
9       90      1
10      100     1
11      110     2
12      112     1
13      113     1
14      114     1
15      115     1
16      116     1
17      117     1
18      118     1
19      119     1
20      122     1

Ecco lo stesso elenco fino a N = 1000.


31
Questo deve essere aggiunto a OEIS
Claudiu,

28
@Claudiu questo viene aggiunto all'OEIS .
user48538

Risposte:


13

Pyth, 44 byte

L/lf_ITs.e.e`sXXNkZYbN=N`b2,Je.f&!_I`ZyZQ0yJ

Provalo online: dimostrazione o suite di test

Un piccolo stupido bug (?) In Pyth ha rovinato una soluzione da 41 byte.

Spiegazione:

L/lf_ITs.e.e`sXXNkZYbN=N`b2
L                             define a function y(b), which returns:
                      =N`b       assign the string representation of b to N
        .e             N         map each (k=Index, b=Value) of N to:
          .e         N             map each (Y=Index, Z=Value) of N to:
              XXNkZbN                switch the kth and Yth value in N
            `s                       get rid of leading zeros
       s                         combine these lists
   f_IT                          filter for palindromes
  l                              length
 /                        2      and divide by 2

,Je.f&!_I`ZyZQ0yJ
   .f        Q0     find the first input() numbers Z >= 0, which satisfy
      !_I`Z            Z is not a palindrom
     &                 and 
           yZ          y(Z) != 0
  e                 get the last number
 J                  and store in J
,J             yJ   print the pair [J, y(J)]

E cos'è questo "stupido piccolo bug (?)"
CalculatorFeline

@CatsAreFluffy Doveva cercare la storia di Github. Riguarda .f. Ecco la richiesta pull che ho fatto a causa di questa domanda: github.com/isaacg1/pyth/pull/151
Jakube

42

CJam, 45 byte

0{{)_s:C,2m*{~Ce\is_W%=},,2/:O!CCW%=|}g}ri*SO

Provalo online!

Come funziona

0          e# Push 0 (candidate).
{          e# Loop:
  {        e#   Loop:
    )_     e#     Increment the candidate and push a copy.
    s:C    e#     Cast to string and save in C.
    ,      e#     Get the length of C, i.e., the number of digits.
    2m*    e#     Push all pairs [i j] where 0 ≤ i,j < length(C).
    {      e#     Filter:
      ~    e#       Unwrap, pushing i and j on the stack.
      Ce\  e#       Swap the elements of C at those indices.
      is   e#       Cast to int, then to string, removing leading zeroes.
      _W%= e#       Copy, reverse and compare.
    },     e#     Keep the pairs for which = returned 1, i.e., palindromes.
    ,2/    e#     Count them and divide the count by 2 ([i j] ~ [j i]).
    :O     e#     Save the result (the order) in O.
    !      e#     Negate logically, so 0 -> 1.
    CCW%=  e#     Compare C with C reversed.
    |      e#     Compute the bitwise NOT of both Booleans.
           e#     This gives 0 iff O is 0 or C is a palindrome.
  }g       e#   Repeat the loop while the result is non-zero.
}ri*       e# Repeat the loop n times, where n is an integer read from STDIN.
           e# This leaves the last candidate (the n-th Dennis number) on the stack.
SO         e# Push a space and the order.

50
Ho già toccato il limite di ripetizione, ma ho dovuto pubblicare la prima risposta.
Dennis,

1
Ugh. Come mi costringo a votare un commento con 42 voti positivi?
NieDzejkob,

Ho ottenuto il 42 ° voto: P
mackycheese21

7

Haskell, 174 byte

import Data.List
p x=x==reverse x
x!y=sum[1|(a,b)<-zip x y,a/=b]==2
o n|x<-show n=sum[1|v<-nub$permutations x,x!v,p$snd$span(<'1')v,not$p x]
f=([(x,o x)|x<-[-10..],o x>0]!!)

p controlla se un elenco è un palindromo.

x!yè Trueiff le liste xe y(che dovrebbero avere la stessa lunghezza) differiscono esattamente in due punti. In particolare, se xè una permutazione di y, x!ydetermina se si tratta di uno "scambio".

o ntrova l'ordine di Dennis di n. Filtra gli swap tra le permutazioni di x = show ne quindi conta quanti di questi swap sono palindromi. La comprensione dell'elenco che esegue questo conteggio ha una guardia in più not (p x), il che significa che tornerà 0se all'inizio nera un palindromo.

Il snd (span (<'1') v)bit è solo di dropWhileun byte più corto; si trasforma "01221"in "1221".

fgli indici da un elenco di (i, o i)dove o i > 0(cioè iè un numero Dennis.) In questo caso si verificherebbe normalmente un errore off-by-one, dato che (!!)conta da 0 ma il problema conta da 1. Sono riuscito a rimediare avviando la ricerca da -10(che si è rivelato essere un numero di Dennis dal mio programma!) spingendo così tutti i numeri nei punti giusti.

f 774lo è (12012,3).


6

Python 2, 176

i=input()
n=9
c=lambda p:`p`[::-1]==`p`
while i:n+=1;x=`n`;R=range(len(x));r=[c(int(x[:s]+x[t]+x[s+1:t]+x[s]+x[t+1:]))for s in R for t in R[s+1:]];i-=any(r)^c(n)
print n,sum(r)

Non riesco a immaginare che il mio codice di scambio sia particolarmente ottimale, ma questo è il migliore che sono stato in grado di ottenere. Inoltre non mi piace la frequenza con cui converto tra stringa e intero ...

Per ogni numero, crea un elenco di a se tutti gli swap di due cifre sono palindromi. Decrementa il contatore quando almeno uno di questi valori è vero e il numero originale non è un palindromo. Dato che 0+Truein python valuta 1la somma dell'elenco finale funziona per l'ordine del numero di Dennis.


5

Ruggine, 390 byte

fn d(mut i:u64)->(u64,i32){for n in 1..{let mut o=0;if n.to_string()==n.to_string().chars().rev().collect::<String>(){continue}let mut s=n.to_string().into_bytes();for a in 0..s.len(){for b in a+1..s.len(){s.swap(a,b);{let t=s.iter().skip_while(|&x|*x==48).collect::<Vec<&u8>>();if t.iter().cloned().rev().collect::<Vec<&u8>>()==t{o+=1}}s.swap(a,b);}}if o>0{i-=1;if i<1{return(n,o)}}}(0,0)}

La nuova Java? : /

Ungolf e commentato:

fn main() {
    let (num, order) = dennis_ungolfed(774);
    println!("{} {}", num, order);  //=> 12012 3
}

fn dennis_ungolfed(mut i: u64) -> (u64, i32) {
    for n in 1.. {
        let mut o = 0;  // the order of the Dennis number
        if n.to_string() == n.to_string().chars().rev().collect::<String>() {
            // already a palindrome
            continue
        }
        let mut s = n.to_string().into_bytes();  // so we can use swap()
        for a in 0..s.len() {  // iterate over every combination of (i, j)
            for b in a+1..s.len() {
                s.swap(a, b);
                // need to start a new block because we're borrowing s
                {
                    let t = s.iter().skip_while(|&x| *x == 48).collect::<Vec<&u8>>();
                    if t.iter().cloned().rev().collect::<Vec<&u8>>() == t { o += 1 }
                }
                s.swap(a, b);
            }
        }
        // is this a Dennis number (order at least 1)?
        if o > 0 {
            // if this is the i'th Dennis number, return
            i -= 1;
            if i == 0 { return (n, o) }
        }
    }
    (0, 0)  // grr this is necessary
}

4

Gelatina , 33 byte (non competitiva)

ṚḌ=
=ċ0^2°;ḌÇ
DŒ!Qç@ÐfDL©Ṡ>ѵ#Ṫ,®

Provalo online!

Come funziona

DŒ!Qç@ÐfDL©Ṡ>ѵ#Ṫ,®  Main link. No arguments.

              µ      Combine the chain to the left into a link.
               #     Find; execute the chain with arguments k = 0, 1, 2, ...
                     until n values of k result in a truthy value, where n is an
                     integer read implicitly from STDIN. Return those n values.

D                      Decimal; convert k to the list of its digits in base 10.
 Œ!                    Generate all permutations of the digits.
   Q                   Unique; deduplicate the list of permutations.
      Ðf               Filter:
    ç@  D                Call the helper link on the second line with the
                         unpermuted digits (D) as left argument, and each
                         permutation as the right one.
                       Keep permutations for which ç returns a truthy value.
         L©            Compute the length (amount of kept permutations) and save
                       it in the register.
           Ṡ           Sign; yield 1 if the length is positive, and 0 otherwise.
            >Ṅ         Compare the sign with the result from the helper link on
                       the first line. This will return 1 if and only if the
                       length is positive and Ñ returns 0.
                Ṫ      Tail; extract the last value of k.
                 ,®    Pair it with the value in the register.


=ċ0^2°;ḌÇ              Helper link. Arguments: A, B (lists of digits)

=                      Compare the corresponding integers in A and B.
 ċ0                    Count the zeroes, i.e., the non-matching integers.
   ^2                  Bitwise XOR the amount with 2.
     °                 Convert to radians. This will yield 0 if exactly two
                       corresponding items of A and B are different ,and a
                       non-integral number otherwise.
      ;                Prepend the result to B.
       Ḍ               Convert the result from decimal to integer. Note that
                       leading zeroes in the argument won't alter the outcome.
        Ç              Call the helper link on the first line.


ṚḌ=                    Helper link. Argument: m (integer)

Ṛ                      Convert m to decimal and reverse the digits.
 Ḍ                     Convert back to integer.
  =                    Compare the result with m.

2

APL, 87

2↓⎕{⍺(2⊃⍵+K⌊~A∧.=⌽A)X,K←+/{⍵∧.=⌽⍵}¨1↓∪,{⍕⍎Y⊣Y[⌽⍵]←⍵⊃¨⊂Y←A}¨∘.,⍨⍳⍴A←⍕X←1+3⊃⍵}⍣{=/2↑⍺}3⍴0

Il corpo del loop restituisce un vettore di 4 numeri: 1) il suo argomento sinistro letto dall'input, 2) il conteggio dei numeri di Dennis finora, 3) il valore corrente di X- il contatore del loop e 4) il suo ordine Kcalcolato come somma dei palindromi entro permutazioni di 1 scambio. Termina quando i primi due elementi diventano uguali e gli ultimi due vengono quindi restituiti come risultato.


2

JavaScript (ES6), 229

Come al solito, JavaScript brilla per la sua inettitudine per la combinatoria (o, forse è la mia inettitudine ...). Qui ottengo tutte le possibili posizioni di swap trovando tutti i numeri binari della lunghezza data e solo 2 di quelli impostati.

Prova a eseguire lo snippet di seguito in Firefox (poiché MSIE è tutt'altro che compatibile con EcmaScript 6 e Chrome non ha ancora i parametri predefiniti)

F=c=>(P=>{for(a=9;c;o&&--c)if(P(n=++a+'',o=0))for(i=1<<n.length;k=--i;[x,y,z]=q,u=n[x],v=n[y],!z&&u-v&&(m=[...n],m[x]=v,m[y]=u,P(+(m.join``))||++o))for(j=0,q=[];k&1?q.push(j):k;k>>=1)++j;})(x=>x-[...x+''].reverse().join``)||[a,o]

// TEST

function go(){ O.innerHTML=F(I.value)}


// Less Golfed
U=c=>{
  P=x=>x-[...x+''].reverse().join``; // return 0 if palindrome 
  
  for(a = 9; // start at 9 to get the first that is known == 10
      c; // loop while counter > 0
      o && --c // decrement only if a Dennis number found
      )
  {  
    o = 0; // reset order count
    ++a;
    if (P(a)) // if not palindrome
    {  
      n = a+''; // convert a to string
      for(i = 1 << n.length; --i; ) 
      {
        j = 0;
        q = [];
        for(k = i; k; k >>= 1)
        {
          if (k & 1) q.push(j); // if bit set, add bit position to q
          ++j;
        } 
        [x,y,z] = q; // position of first,second and third '1' (x,y must be present, z must be undefined)
        u = n[x], v = n[y]; // digits to swap (not valid if they are equal)
        if (!z && u - v) // fails if z>0 and if u==v or u or v are undefined
        {
          m=[...n]; // convert to array
          m[x] = v, m[y] = u; // swap digits
          m = +(m.join``); // from array to number (evenutally losing leading zeroes)
          if (!P(m)) // If palindrome ...
            ++o; // increase order count 
        }  
      }
    }
  }  
  return [a,o];
}

//////
go()
<input id=I value=774><button onclick="go()">-></button> <span id=O></span>


1

awk, 199

{for(;++i&&d<$0;d+=o>0)for(o=j=_;j++<l=length(i);)for(k=j;k++<l;o+=v!=i&&+r~s){split(t=i,c,v=s=r=_);c[j]+=c[k]-(c[k]=c[j]);for(e in c){r=r c[e];s=s||c[e]?c[e]s:s;v=t?v t%10:v;t=int(t/10)}}print--i,o}

Struttura

{
    for(;++i&&d<$0;d+=o>0)
        for(o=j=_;j++<l=length(i);)
            for(k=j;k++<l;o+=v!=i&&+r~s)
            {
                split(t=i,c,v=s=r=_);
                c[j]+=c[k]-(c[k]=c[j]);
                for(e in c)
                {
                    r=r c[e];
                    s=s||c[e]?c[e]s:s;
                    v=t?v t%10:v;
                    t=int(t/10)
                }
            }
    print--i,o
}

uso

Incolla questo sulla tua console e sostituisci il numero dopo echo, se vuoi

echo 20 | awk '{for(;++i&&d<$0;d+=o>0)for(o=j=_;j++<l=length(i);)for(k=j;k++<l;o+=v!=i&&+r~s){split(t=i,c,v=s=r=_);c[j]+=c[k]-(c[k]=c[j]);for(e in c){r=r c[e];s=s||c[e]?c[e]s:s;v=t?v t%10:v;t=int(t/10)}}print--i,o}'

Diventa lento a numeri più alti;)

Versione riutilizzabile non golfata

{
    dennisFound=0

    for(i=0; dennisFound<$0; )
    {
        i++
        order=0

        for(j=0; j++<length(i); )
        {
            for(k=j; k++<length(i); )
            {
                split(i, digit, "")
                digit[j]+=digit[k]-(digit[k]=digit[j]) # swap digits

                tmp=i
                iRev=iFlip=iFlipRev=""

                for(e in digit)
                {
                    if(tmp>0)                        # assemble reversed i
                        iRev=iRev tmp%10
                    tmp = int( tmp/10 )

                    iFlip=iFlip digit[e]             # assemble flipped i

                    if(iFlipRev>0 || digit[e]>0)     # assemble reversed flipped i
                        iFlipRev=digit[e] iFlipRev   # without leading zeros
                }
                if(iRev!=i && 0+iFlip==iFlipRev) order++  # i is not a palindrome,
            }                                             # but flipped i is
        }
        if(order>0) dennisFound++
    }
    print i, order
}

1

Ruby, 156

->i{s=?9
(o=0;(a=0...s.size).map{|x|a.map{|y|j=s+'';j[x],j[y]=j[y],j[x];x>y&&j[/[^0].*/]==$&.reverse&&o+=1}}
o<1||s==s.reverse||i-=1)while i>0&&s.next!;[s,o]}

Utilizza la funzione Ruby in cui "19".next!restituisce la chiamata "20"per evitare di dover convertire i tipi avanti e indietro; usiamo solo una regex per ignorare il comando 0s. Scorre tutte le coppie di posizioni delle stringhe per verificare la presenza di interruttori palindromici. Inizialmente ho scritto questa funzione ricorsiva, ma busta lo stack.

L'output per 774 è ["12012", 3](rimuovere le virgolette costerebbe 4 byte in più, ma penso che le specifiche li consentano).

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.