Gere números de Dennis

69

Este desafio é uma homenagem ao usuário do PPCG Dennis por ganhar a parte dos ladrões do The Programming Language Quiz .

Olhando para a página de perfil PPCG de Dennis , podemos ver algumas coisas bastante impressionantes:

Perfil do Dennis

Atualmente, ele tem mais de sessenta e oito mil reputação, o que o coloca em segundo lugar no ranking geral , ultrapassando o terceiro lugar em quase trinta mil. Recentemente, ele venceu nossa eleição para um novo moderador e recebeu um novo diamante brilhante ao lado de seu nome. Mas, pessoalmente, acho que a parte mais interessante sobre Dennis é seu número de identificação de usuário PPCG: 12012.

À primeira vista, 12012quase parece um palíndromo , um número que lê o mesmo quando invertido, mas está um pouco fora. Pode se tornar o palíndromo 21012se trocarmos as posições do primeiro 1e 2, e pode se tornar o palíndromo 12021se trocarmos o último 1e 2. Além disso, seguindo a convenção de que zeros à esquerda em um número não são gravados, troque o primeiro 1e os 0resultados por, 02112ou melhor, 2112qual é outro palíndromo.

Vamos definir um número de Dennis como um número inteiro positivo que não é palindrômico, mas que pode ser transformado em um palíndromo, trocando as posições de pelo menos um par de dois dígitos. A ordem de um número de Dennis é o número de pares distintos de dígitos que podem ser trocados para formar um palíndromo (não necessariamente distinto).

Assim, a fim de 12012se desde 3 3 pares distintos de seus algarismos ( 12012, , ) podem ser trocadas para produzir palindromas. passa a ser o menor número de 3 Dennis da ordem.120121201212012

10é o menor número de Dennis e tem a ordem 1 porque alternar entre 1e 001aka 1que é um palíndromo.

Os zeros iniciais imaginários de um número não contam como dígitos comutáveis. Por exemplo, alterar 8908a 08908e trocando os dois primeiros dígitos para obter o palíndromo 80908é inválido. 8908não é um número de Dennis.

Pode-se dizer que os números não-Dennis têm a ordem 0.

Desafio

Escreva um programa ou função que receba um número inteiro positivo N e imprima ou retorne o enésimo menor número de Dennis, juntamente com a ordem em algum formato razoável, como 12012 3ou (12012, 3).

Por exemplo, 12012é o número 774th Dennis, portanto, se 774é a entrada para o seu programa, a saída deve ser algo como 12012 3. (Curiosamente, 774 é outro número de Dennis.)

O código mais curto em bytes vence.

Aqui estão os 20 primeiros números de Dennis e seus pedidos de referência:

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

Aqui está a mesma lista até N = 1000.

Passatempos de Calvin
fonte
31
Isso deve ser adicionado ao OEIS
Claudiu
28
@ Claudiu, isso é adicionado ao OEIS.
precisa saber é o seguinte

Respostas:

13

Pitão, 44 ​​bytes

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

Experimente on-line: Demonstration or Test Suite

Um bug estúpido (?) Em Pyth arruinou uma solução de 41 bytes.

Explicação:

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
fonte
E o que é esse 'inseto estúpido (?)'
CalculatorFeline
@CatsAreFluffy Teve que pesquisar a história do Github. Isso diz respeito .f. Aqui está a solicitação de recebimento que eu fiz por causa desta questão: github.com/isaacg1/pyth/pull/151
Jakube
42

CJam, 45 bytes

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

Experimente online!

Como 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
fonte
50
Já atingi o limite de repetições, mas tive que postar a primeira resposta.
Dennis
11
Ugh. Como eu me forço a fazer um voto positivo com 42 votos positivos?
NieDzejkob 13/08/19
Eu tenho o 42º
voto positivo
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 verifica se uma lista é um palíndromo.

x!yé Truese as listas xe y(que devem ter o mesmo comprimento) diferem exatamente em dois lugares. Especificamente, se xé uma permutação de y, x!ydetermina se é uma "troca".

o nencontra a ordem de Dennis de n. Ele filtra os swaps entre as permutações de x = show ne depois conta quantos desses swaps são palíndromos. A compreensão da lista que realiza essa contagem tem uma proteção extra not (p x), o que significa que ela retornará 0se nfosse um palíndromo para começar.

O snd (span (<'1') v)bit é apenas dropWhileum byte mais curto; isso se "01221"transforma "1221".

fíndices de uma lista de (i, o i)onde o i > 0(ou seja, ié um número de Dennis.) Normalmente, haveria um erro de um por um aqui, como (!!)conta de 0, mas o problema conta de 1. Consegui remediar isso iniciando a pesquisa a partir de -10(qual acabou sendo considerado um número de Dennis pelo meu programa!) empurrando todos os números para os pontos certos.

f 774é (12012,3).

Lynn
fonte
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)

Não consigo imaginar que meu código de troca seja particularmente ideal, mas é o melhor que pude obter. Também não gosto da frequência com que converto entre string e número inteiro ...

Para cada número, ele cria uma lista de se todos os swaps de dois dígitos são palíndromos. Ele diminui o contador quando pelo menos um desses valores é verdadeiro e o número original não é um palíndromo. Uma vez que 0+Trueem python avalia 1a soma da lista final, trabalha pela ordem do número de Dennis.

FryAmTheEggman
fonte
5

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

O novo Java? : /

Ungolfed e comentou:

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
}
Maçaneta da porta
fonte
4

Gelatina , 33 bytes (não concorrente)

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

Experimente online!

Como 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
fonte
2

APL, 87

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

O corpo do loop retorna um vetor de 4 números: 1) seu argumento esquerdo lido da entrada, 2) contagem de números de Dennis até agora, 3) valor atual de X- o contador de loop e 4) sua ordem Kcalculada como soma dos palíndromos dentro de permutações de 1 swap. Ele termina quando os dois primeiros elementos se tornam iguais e os dois últimos são retornados como resultado.

user44932
fonte
2

JavaScript (ES6), 229

Como de costume, o JavaScript brilha por sua inaptidão para combinações (ou, talvez seja a minha inaptidão ...). Aqui eu recebo todas as posições de swap possíveis, encontrando todos os números binários do comprimento especificado e apenas 2 conjuntos.

Teste a execução do snippet abaixo no Firefox (como o MSIE está longe de ser compatível com o EcmaScript 6 e o ​​Chrome ainda não possui os parâmetros padrão)

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

Estrutura

{
    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

Cole isso no seu console e substitua o número depois echo, se desejar

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

Fica lento em números mais altos;)

Versão reutilizável não destruída

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

Usa o recurso Ruby, em que a chamada "19".next!retorna "20"para evitar a conversão de tipos; nós apenas usamos um regex para ignorar a liderança 0s. Repete todos os pares de posições das strings para verificar se há comutadores palindrômicos. Originalmente, escrevi isso como uma função recursiva, mas ela destrói a pilha.

A saída para 774 é ["12012", 3](remover as aspas custaria mais 4 bytes, mas acho que a especificação permite).

histocrata
fonte