Generar números de Dennis

69

Este desafío es un homenaje al usuario de PPCG Dennis por ganar la parte de ladrones de The Programming Language Quiz .

Mirando la página de perfil PPCG de Dennis podemos ver algunas cosas bastante impresionantes:

Perfil de Dennis

Actualmente tiene más de sesenta y ocho mil reputación, lo que lo convierte en el segundo en general en representación , superando el tercer lugar en casi treinta mil. Recientemente ganó nuestra elección para un nuevo moderador y obtuvo un nuevo diamante brillante al lado de su nombre. Pero personalmente creo que la parte más interesante de Dennis es su número de identificación de usuario PPCG: 12012.

A primera vista, 12012casi parece un palíndromo , un número que dice lo mismo cuando se invierte, pero está un poco apagado. Puede convertirse en el palíndromo 21012si intercambiamos las posiciones del primero 1y 2, y puede convertirse en el palíndromo 12021si intercambiamos el último 1y 2. Además, siguiendo la convención de que los ceros a la izquierda en un número no se escriben, intercambian el primero 1y los 0resultados en 02112o más bien 2112que es otro palíndromo.

Definamos un número de Dennis como un entero positivo que no es palindrómico en sí mismo, pero que puede convertirse en un palíndromo intercambiando las posiciones de al menos un par de dos dígitos. El orden de un número de Dennis es el número de pares distintos de dígitos que se pueden intercambiar para hacer un palíndromo (no necesariamente distinto).

Así que el orden de 12012es 3 desde 3 pares distintos de sus dígitos ( 12012, , ) se pueden intercambiar alrededor para producir palíndromos. pasa a ser el menor número de orden 3 Dennis.120121201212012

10es el número de Dennis más pequeño y tiene el orden 1 porque al cambiar 1y 0da 01aka, 1que es un palíndromo.

Los ceros imaginarios iniciales de un número no cuentan como dígitos conmutables. Por ejemplo, el cambio 8908de 08908e intercambiando los dos primeros dígitos para obtener el palíndromo 80908es válido. 8908No es un número de Dennis.

Se podría decir que los números que no son de Dennis tienen orden 0.

Desafío

Escriba un programa o función que tome un entero positivo N e imprima o devuelva el enésimo número Dennis más pequeño junto con su orden en algún formato razonable como 12012 3o (12012, 3).

Por ejemplo, 12012es el número 774 de Dennis, por lo que si 774es la entrada a su programa, la salida debería ser algo así 12012 3. (Curiosamente, 774 es otro número de Dennis).

El código más corto en bytes gana.

Aquí están los primeros 20 números de Dennis y sus órdenes de referencia:

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

Aquí está la misma lista hasta N = 1000.

Pasatiempos de Calvin
fuente
31
Esto tiene que ser agregado a OEIS
Claudiu
28
@Claudiu esto se agrega a la OEIS.
user48538

Respuestas:

13

Pyth, 44 bytes

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

Pruébelo en línea: Demostración o conjunto de pruebas

Un pequeño error estúpido (?) En Pyth arruinó una solución de 41 bytes.

Explicación:

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
fuente
¿Y qué es este 'pequeño insecto estúpido (?)'
CalculatorFeline
@CatsAreFluffy Tuve que buscar la historia de Github. Se refiere .f. Aquí está la solicitud de extracción que hice debido a esta pregunta: github.com/isaacg1/pyth/pull/151
Jakube
42

CJam, 45 bytes

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

Pruébalo en línea!

Cómo funciona

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
fuente
50
Ya llegué al límite de repeticiones, pero tuve que publicar la primera respuesta.
Dennis
1
Ugh ¿Cómo me obligo a votar un comentario con 42 votos a favor?
NieDzejkob
Obtuve el 42o voto a favor
7

Haskell, 174 bytes

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 comprueba si una lista es un palíndromo.

x!yes Truesi las listas xy y(que deberían tener la misma longitud) difieren exactamente en dos lugares. Específicamente, si xes una permutación de y, x!ydetermina si es un "intercambio".

o nencuentra el orden Dennis de n. Filtra los intercambios entre las permutaciones de x = show n, y luego cuenta cuántos de esos intercambios son palíndromos. La comprensión de la lista que realiza este recuento tiene una protección adicional not (p x), lo que significa que volverá 0si npara empezar era un palíndromo.

El snd (span (<'1') v)bit es solo dropWhileun byte más corto; se convierte "01221"en "1221".

fíndices de una lista de (i, o i)dónde o i > 0( ies decir, es un número de Dennis). Normalmente, aquí habría un error de uno por uno, ya que (!!)cuenta desde 0 pero el problema cuenta desde 1. Logré remediar esto iniciando la búsqueda desde -10(que resultó ser considerado un número de Dennis por mi programa!) empujando así todos los números en los lugares correctos.

f 774es (12012,3).

Lynn
fuente
6

Pitón 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)

No puedo imaginar que mi código de intercambio sea particularmente óptimo, pero esto es lo mejor que he podido obtener. Tampoco me gusta la frecuencia con la que convierto entre cadena y entero ...

Para cada número, crea una lista de si todos los intercambios de dos dígitos son palíndromos. Disminuye el contador cuando al menos uno de estos valores es verdadero, y el número original no es un palíndromo. Dado que 0+Trueen python se evalúa a 1la suma de la lista final funciona para el orden del número de Dennis.

FryAmTheEggman
fuente
5

Óxido, 390 bytes

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

El nuevo Java? : /

Ungolfed y comentó:

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
}
Pomo de la puerta
fuente
4

Jalea , 33 bytes (no competitiva)

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

Pruébalo en línea!

Cómo funciona

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
fuente
2

APL, 87

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

El cuerpo del bucle devuelve un vector de 4 números: 1) su argumento izquierdo leído desde la entrada, 2) recuento de números de Dennis hasta el momento, 3) valor actual de X- el contador del bucle y 4) su orden Kcalculado como la suma de palíndromos dentro de permutaciones de 1 intercambio. Termina cuando los dos primeros elementos se vuelven iguales y los dos últimos se devuelven como resultado.

usuario44932
fuente
2

JavaScript (ES6), 229

Como de costumbre, JavaScript destaca por su ineptitud para la combinatoria (o tal vez sea mi ineptitud ...). Aquí obtengo todas las posiciones de intercambio posibles para encontrar todos los números binarios de la longitud dada y solo 2 unidades establecidas.

Pruebe a ejecutar el fragmento a continuación en Firefox (ya que MSIE está lejos de ser compatible con EcmaScript 6 y Chrome aún no tiene los parámetros predeterminados)

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

Estructura

{
    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

Pegue esto en su consola y reemplace el número después echo, si lo desea

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

Se vuelve lento en números más altos;)

Versión reutilizable sin golf

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

Utiliza la función Ruby donde se "19".next!devuelve la llamada "20"para evitar tener que convertir tipos de un lado a otro; solo usamos una expresión regular para ignorar el liderazgo 0s. Itera sobre todos los pares de posiciones de cuerda para verificar si hay interruptores palindrómicos. Originalmente escribí esto como una función recursiva pero rompe la pila.

La salida para 774 es ["12012", 3](eliminar las comillas costaría 4 bytes más, pero creo que la especificación lo permite).

histocrat
fuente