Générer des numéros de Dennis

69

Ce défi est un hommage à l' utilisateur de PPCG, Dennis, qui a remporté le jeu des voleurs du Quiz sur le langage de programmation .

En regardant la page de profil de PPCG de Dennis, on peut voir des choses assez impressionnantes:

Profil de Dennis

Il a actuellement plus de soixante-huit mille joueurs, ce qui le place au deuxième rang des représentants , dépassant de près de trente mille la troisième place. Il a récemment remporté notre élection pour un nouveau modérateur et a reçu un nouveau diamant brillant à côté de son nom. Mais personnellement, je pense que la partie la plus intéressante de Dennis est son numéro d’identifiant PPCG: 12012.

À première vue, cela 12012ressemble presque à un palindrome , un nombre qui lit la même chose une fois inversé, mais un peu éteint. Il peut devenir le palindrome 21012si nous échangeons les positions du premier 1et 2, et il peut devenir le palindrome 12021si nous échangeons le dernier 1et 2. De plus, suivant la convention voulant que les zéros non-majuscules d’un nombre ne soient pas écrits, permutez le premier 1et les 0résultats 02112ou plutôt 2112un autre palindrome.

Définissons un nombre de Dennis comme un entier positif qui n'est pas le palindrome lui-même mais qui peut être transformé en un palindrome en permutant les positions d'au moins une paire de deux chiffres. L' ordre d'un numéro de Dennis est le nombre de paires de chiffres distinctes qui peuvent être échangés pour former un palindrome (pas nécessairement distinct).

Donc , l'ordre 12012est 3 depuis trois paires distinctes de ses chiffres ( 12012, , ) peuvent être interchangés pour produire palindromes. se trouve être le plus petit ordre numéro 3 Dennis.120121201212012

10est le plus petit numéro de Dennis et a l'ordre 1 parce que commuter autour de 1et 0donne 01aka 1qui est un palindrome.

Les zéros non significatifs d'un nombre ne comptent pas comme des chiffres commutables. Par exemple, le changement 8908de 08908et échanger les deux premiers chiffres pour obtenir le palindrome 80908est invalide. 8908n'est pas un numéro de Dennis.

On pourrait dire que les nombres non-Dennis ont un ordre 0.

Défi

Ecrivez un programme ou une fonction qui prend un entier positif N et imprime ou renvoie le Nième plus petit nombre de Dennis avec son ordre dans un format raisonnable, tel que 12012 3ou (12012, 3).

Par exemple, 12012est le 774ème numéro de Dennis, donc si 774est l’entrée de votre programme, le résultat devrait ressembler à quelque chose 12012 3. (Curieusement, 774 est un autre numéro de Dennis.)

Le code le plus court en octets gagne.

Voici les 20 premiers numéros de Dennis et leurs commandes pour référence:

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

Voici la même liste jusqu'à N = 1000.

Les passe-temps de Calvin
la source
31
Ceci doit être ajouté à OEIS
Claudiu
28
@Claudiu, cela est ajouté à l'OEIS.
user48538

Réponses:

13

Pyth, 44 octets

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

Essayez-le en ligne: démonstration ou suite de tests

Un petit bug stupide (?) Dans Pyth a gâché une solution de 41 octets.

Explication:

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)]
Jakube
la source
Et quelle est cette "petite bête stupide (?)"
CalculatorFeline
@CatsAreFluffy Il a fallu consulter l'historique de Github. Cela concerne .f. Voici la demande de traction que j'ai faite à cause de cette question: github.com/isaacg1/pyth/pull/151
Jakube
42

CJam, 45 octets

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

Essayez-le en ligne!

Comment ça fonctionne

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.
Dennis
la source
50
J'ai déjà atteint le plafond des représentants, mais je devais poster la première réponse.
Dennis
1
Pouah. Comment puis-je me forcer à faire passer un commentaire à 42 votes plus haut?
NieDzejkob
J'ai eu le 42ème vote positif: P
mackycheese21
7

Haskell, 174 octets

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 vérifie si une liste est un palindrome.

x!yest Truessi les listes xet y( ce qui devrait avoir la même longueur) diffèrent dans exactement deux endroits. Plus précisément, si xest une permutation de y, x!ydétermine s'il s'agit d'un "échange".

o ntrouve l'ordre de Dennis n. Il filtre pour les échanges entre les permutations de x = show n, puis compte combien de ces échanges sont des palindromes. La compréhension de liste qui effectue ce compte a une garde supplémentaire not (p x), ce qui signifie qu'elle reviendra 0s'il ns'agissait d'un palindrome pour commencer.

Le snd (span (<'1') v)bit est juste dropWhilequ'un octet plus court; il se transforme "01221"en "1221".

findex à partir d’une liste d’ (i, o i)o i > 0(c’est-à i- dire un numéro de Dennis.) Il y aurait normalement une erreur unique, comme (!!)compte à partir de 0 mais le problème compte à partir de 1. J’ai réussi à y remédier en démarrant la recherche -10(à partir de s'est avéré être considéré comme un numéro Dennis par mon programme!), plaçant ainsi tous les numéros aux bons endroits.

f 774est (12012,3).

Lynn
la source
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)

Je ne peux pas imaginer que mon code d'échange est particulièrement optimal, mais c'est le meilleur que j'ai pu obtenir. Je n'aime pas non plus combien de fois je convertis entre chaîne et entier ...

Pour chaque numéro, il crée une liste indiquant si tous les échanges de deux chiffres sont des palindromes. Il décrémente le compteur lorsqu'au moins l'une de ces valeurs est vraie et que le nombre d'origine n'est pas un palindrome. Étant donné que 0+Truepython évalue à 1la somme de la liste finale fonctionne pour l'ordre du nombre de Dennis.

FryAmTheEggman
la source
5

Rouille, 390 octets

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 nouvelle Java? : /

Ungolfed et commenté:

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
}
Poignée de porte
la source
4

Gelée , 33 octets (non concurrente)

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

Essayez-le en ligne!

Comment ça fonctionne

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.
Dennis
la source
2

APL, 87

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

Le corps de la boucle renvoie un vecteur de 4 nombres: 1) son argument de gauche lu à partir de l'entrée, 2) le nombre de nombres de Dennis jusqu'à présent, 3) la valeur actuelle du Xcompteur de boucle et 4) son ordre Kcalculé comme la somme des palindromes. dans les permutations 1-swap. Il se termine lorsque les deux premiers éléments deviennent égaux et que les deux derniers sont alors renvoyés en tant que résultat.

utilisateur44932
la source
2

JavaScript (ES6), 229

Comme d'habitude, JavaScript brille par son incompétence pour la combinatoire (ou, peut-être est-ce mon incompétence ...). Ici, j’obtiens toutes les positions d’échange possibles recherchant tous les nombres binaires de la longueur donnée et seulement 2 unités.

Testez l'exécution de l'extrait de code ci-dessous dans Firefox (MSIE étant loin d'être conforme à EcmaScript 6 et à Chrome, les paramètres par défaut sont toujours manquants)

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>

edc65
la source
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}

Structure

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

Usage

Collez-le sur votre console et remplacez le numéro après echosi vous le souhaitez.

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

Il devient lent à des nombres plus élevés;)

Version réutilisable non-golfée

{
    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
}
Cabbie407
la source
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]}

Utilise la fonction Ruby où l’appel "19".next!revient "20"pour éviter d’avoir à convertir les types dans les deux sens; nous utilisons simplement une regex pour ignorer les majuscules 0s. Parcourt toutes les paires de positions de chaîne pour vérifier les commutateurs palindromiques. A l'origine, j'avais écrit cela comme une fonction récursive, mais cela volait la pile.

La sortie pour 774 est ["12012", 3](supprimer les guillemets coûterait 4 octets de plus, mais je pense que les spécifications le leur permettent).

histocrate
la source