Hasilkan Bilangan Dennis

69

Tantangan ini merupakan penghargaan bagi pengguna PPCG, Dennis, karena memenangkan bagian perampok dari The Programming Language Quiz .

Melihat halaman profil PPCG Dennis, kita dapat melihat beberapa hal yang cukup mengesankan:

Profil Dennis

Dia saat ini memiliki lebih dari enam puluh delapan ribu reputasi, menjadikannya nomor dua di seluruh rep , melampaui tempat ketiga dengan hampir tiga puluh ribu. Dia baru-baru ini memenangkan pemilihan kami untuk moderator baru dan mendapatkan berlian baru yang mengilap di sebelah namanya. Tapi saya pribadi berpikir bagian paling menarik tentang Dennis adalah nomor ID pengguna PPCG-nya: 12012.

Pada pandangan pertama 12012hampir terlihat seperti palindrom , angka yang membaca sama ketika dibalik, tetapi sedikit batal. Itu bisa menjadi palindrome 21012jika kita menukar posisi yang pertama 1dan 2, dan itu bisa menjadi palindrom 12021jika kita menukar yang terakhir 1dan yang lain 2. Juga, mengikuti konvensi bahwa angka nol terdepan dalam angka tidak ditulis, bertukar angka pertama 1dan 0hasilnya 02112atau lebih tepatnya 2112yang merupakan palindrom lain.

Mari kita mendefinisikan bilangan Dennis sebagai bilangan bulat positif yang bukan palindromik itu sendiri tetapi dapat dibuat menjadi palindrom dengan menukar posisi setidaknya satu pasangan dari dua digit. The rangka dari sejumlah Dennis adalah jumlah pasangan yang berbeda dari angka yang dapat ditukarkan untuk membuat (tidak selalu berbeda) palindrom.

Jadi urutan 12012adalah 3 sejak 3 pasang yang berbeda dari digit ( 12012, , ) dapat ditukarkan sekitar untuk menghasilkan palindrom. kebetulan menjadi urutan terkecil 3 nomor Dennis.120121201212012

10adalah nomor Dennis terkecil dan memiliki urutan 1 karena beralih di sekitar 1dan 0memberi 01alias 1yang merupakan palindrome.

Nol terkemuka imajiner nomor tidak dihitung sebagai digit yang dapat diganti. Misalnya, mengubah 8908ke 08908dan menukar dua digit pertama untuk mendapatkan palindrom yang 80908tidak valid. 8908bukan nomor Dennis.

Angka-angka non-Dennis dapat dikatakan memiliki pesanan 0.

Tantangan

Tulis program atau fungsi yang mengambil dalam bilangan bulat positif N dan mencetak atau mengembalikan angka Dennis terkecil ke-N beserta urutannya dalam beberapa format yang masuk akal seperti 12012 3atau (12012, 3).

Sebagai contoh, 12012adalah angka Dennis ke-774 jadi jika 774input untuk program Anda, hasilnya harus seperti 12012 3. (Anehnya, 774 adalah nomor Dennis lain.)

Kode terpendek dalam byte menang.

Berikut adalah 20 nomor Dennis pertama dan pesanan mereka untuk referensi:

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

Berikut adalah daftar yang sama hingga N = 1000.

Hobi Calvin
sumber
31
Ini harus ditambahkan ke OEIS
Claudiu
28
@Claudiu ini adalah ditambahkan ke Oei.
user48538

Jawaban:

13

Pyth, 44 byte

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

Cobalah online: Demonstrasi atau Test Suite

Bug kecil bodoh (?) Di Pyth merusak solusi 41 byte.

Penjelasan:

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
sumber
Dan apa ini 'bug kecil bodoh (?)'
CalculatorFeline
@CatsAreFluffy Harus mencari sejarah Github. Itu menyangkut .f. Inilah permintaan tarik yang saya buat karena pertanyaan ini: github.com/isaacg1/pyth/pull/151
Jakube
42

CJam, 45 byte

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

Cobalah online!

Bagaimana itu bekerja

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
sumber
50
Saya sudah mencapai batas rep, tetapi saya harus memposting jawaban pertama.
Dennis
1
Ugh. Bagaimana cara saya memaksa diri saya untuk memberikan komentar dengan 42 upvotes?
NieDzejkob
Saya mendapat upvote ke-42: 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 memeriksa apakah suatu daftar adalah palindrome.

x!yJika Truedaftar xdan y(yang harus memiliki panjang yang sama) berbeda persis di dua tempat. Secara khusus, jika xpermutasi y, x!ymenentukan apakah itu merupakan "swap".

o nmenemukan urutan Dennis n. Ini menyaring untuk swap di antara permutasi x = show n, dan kemudian menghitung berapa banyak dari swap tersebut adalah palindrom. Pemahaman daftar yang melakukan penghitungan ini memiliki penjaga ekstra not (p x), yang berarti akan kembali 0jika nmerupakan palindrom untuk memulai.

The snd (span (<'1') v)bit hanya dropWhiletapi satu byte lebih pendek; itu berubah "01221"menjadi "1221".

findeks dari daftar di (i, o i)mana o i > 0(yaitu iadalah nomor Dennis.) Biasanya ada kesalahan off-by-one di sini, karena (!!)dihitung dari 0 tetapi masalahnya dihitung dari 1. Saya berhasil memperbaiki ini dengan memulai pencarian dari -10(yang ternyata dianggap sebagai nomor Dennis oleh program saya!) sehingga mendorong semua angka ke tempat yang tepat.

f 774adalah (12012,3).

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

Saya tidak dapat membayangkan bahwa kode swapping saya sangat optimal, tetapi ini adalah yang terbaik yang bisa saya dapatkan. Saya juga tidak suka seberapa sering saya mengkonversi antara string dan integer ...

Untuk setiap angka, ini membuat daftar apakah semua swap dua digit adalah palindrom. Ini mengurangi penghitung ketika setidaknya salah satu dari nilai-nilai ini benar, dan nomor aslinya bukan palindrom. Karena 0+Truedalam python mengevaluasi 1jumlah dari daftar akhir berfungsi untuk urutan nomor Dennis.

FryAmTheEggman
sumber
5

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

Java baru? : /

Tidak dikumpulkan dan berkomentar:

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
}
Gagang pintu
sumber
4

Jelly , 33 byte (tidak bersaing)

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

Cobalah online!

Bagaimana itu bekerja

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

APL, 87

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

Tubuh loop mengembalikan vektor 4 angka: 1) argumen kirinya membaca dari input, 2) menghitung angka Dennis sejauh ini, 3) nilai saat ini X- penghitung loop, dan 4) pesanannya Kdihitung sebagai jumlah palindrom dalam permutasi 1-swap. Ini berakhir ketika dua elemen pertama menjadi sama dan dua elemen terakhir kemudian dikembalikan sebagai hasilnya.

pengguna44932
sumber
2

JavaScript (ES6), 229

Seperti biasa, JavaScript bersinar karena ketidakmampuannya untuk kombinatorik (atau, mungkin ketidakmampuan saya ...). Di sini saya mendapatkan semua posisi swap kemungkinan menemukan semua angka biner dari panjang yang diberikan dan hanya 2 yang ditetapkan.

Tes menjalankan cuplikan di bawah ini di Firefox (karena MSIE jauh dari patuh EcmaScript 6 dan Chrome masih kehilangan parameter default)

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

Struktur

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

Pemakaian

Tempel ini ke konsol Anda dan ganti nomor setelahnya echo, jika Anda mau

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

Semakin lambat pada angka yang lebih tinggi;)

Versi yang dapat digunakan kembali yang tidak dikumpulkan

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

Menggunakan fitur Ruby tempat panggilan "19".next!kembali "20"untuk menghindari keharusan mengubah jenis bolak-balik; kami hanya menggunakan regex untuk mengabaikan memimpin 0s. Iterasikan semua pasang posisi string untuk memeriksa sakelar palindrom. Saya awalnya menulis ini fungsi rekursif tapi itu merusak tumpukan.

Output untuk 774 adalah ["12012", 3](menghapus tanda kutip akan dikenakan biaya 4 byte lebih tetapi saya pikir spec memungkinkan mereka).

histokrat
sumber