Dennis-Nummern generieren


69

Diese Herausforderung ist eine Hommage an den PPCG- Benutzer Dennis , der den Räuberteil des Programmiersprachen-Quiz gewonnen hat .

Wenn wir Dennis 'PPCG-Profilseite betrachten , können wir einige ziemlich beeindruckende Dinge sehen:

Dennis 'Profil

Er hat derzeit mehr als acht-sechzig tausend Ruf, was ihn an zweiter Stelle in Gesamt rep und übertrifft damit die dritten Platz von fast dreißigtausend. Er hat vor kurzem gewann unsere Wahl für einen neuen Moderator und bekam einen glänzenden neuen Diamanten neben seinen Namen. Aber ich persönlich denke, der interessanteste Teil an Dennis ist seine PPCG-Benutzer-ID-Nummer: 12012.

Auf den ersten Blick 12012sieht es fast wie ein Palindrom aus , eine Zahl, die umgekehrt dasselbe liest, aber ein wenig verkehrt ist. Es kann das Palindrom werden, 21012wenn wir die Positionen des ersten 1und vertauschen 2, und es kann das Palindrom werden, 12021wenn wir das letzte 1und vertauschen 2. Befolgen Sie außerdem die Konvention, dass führende Nullen in einer Zahl nicht geschrieben werden, und tauschen Sie die ersten 1und die 0Ergebnisse aus, 02112oder vielmehr, 2112was ein anderes Palindrom ist.

Definieren wir eine Dennis-Zahl als positive Ganzzahl, die selbst nicht palindrom ist, sondern durch Vertauschen der Positionen von mindestens einem Paar von zwei beliebigen Ziffern in ein Palindrom umgewandelt werden kann. Die Reihenfolge einer Dennis-Zahl ist die Anzahl unterschiedlicher Ziffernpaare, die ausgetauscht werden können, um ein (nicht notwendigerweise unterschiedliches) Palindrom zu bilden.

So ist die Reihenfolge der 120123 , da 3 verschiedene Paare ihrer Ziffern ( 12012, , ) um Palindrome zu erzeugen , ausgelagert werden. zufällig ist es die kleinste 3-Dennis-Zahl.120121201212012

10ist die kleinste Dennis-Zahl und hat die Ordnung 1, weil das umschalten 1und aka was ein Palindrom 0ergibt .011

Die imaginären führenden Nullen einer Zahl zählen nicht als umschaltbare Ziffern. Zum Beispiel ändert 8908an 08908und die ersten beiden Ziffern Vertauschen der Palindrom zu bekommen 80908ist ungültig. 8908ist keine Dennis-Nummer.

Man könnte sagen, dass Nicht-Dennis-Nummern die Ordnung 0 haben.

Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die eine positive ganze Zahl N aufnimmt und die N-kleinste Dennis-Zahl zusammen mit ihrer Reihenfolge in einem vernünftigen Format wie 12012 3oder ausgibt oder zurückgibt (12012, 3).

Beispiel: 12012Ist die 774. Dennis-Nummer 774, sollte die Ausgabe etwa so lauten, wenn es sich um die Eingabe für Ihr Programm handelt 12012 3. (Seltsamerweise ist 774 eine andere Dennis-Nummer.)

Der kürzeste Code in Bytes gewinnt.

Hier sind die ersten 20 Dennis-Nummern und ihre Referenzbestellungen:

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

Hier ist die gleiche Liste bis zu N = 1000.


31
Dies muss zu OEIS
Claudiu

28
@Claudiu Dies wird dem OEIS hinzugefügt.
user48538

Antworten:


13

Pyth, 44 Bytes

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

Probieren Sie es online aus: Demo oder Test Suite

Ein dummer kleiner Fehler (?) In Pyth hat eine 41-Byte-Lösung ruiniert.

Erläuterung:

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

Und was ist das für ein 'dummer kleiner Fehler (?)'
CalculatorFeline

@CatsAreFluffy Musste die Github-Geschichte nachschlagen. Es geht darum .f. Hier ist die Pull-Anfrage, die ich wegen dieser Frage gestellt habe: github.com/isaacg1/pyth/pull/151
Jakube

42

CJam, 45 Bytes

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

Probieren Sie es online!

Wie es funktioniert

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
Ich habe die rep Kappe schon getroffen, aber ich musste die erste Antwort posten.
Dennis

1
Pfui. Wie zwinge ich mich dazu, einen Kommentar mit 42 positiven Stimmen zu bewerten?
NieDzejkob

Ich habe die 42. positive Bewertung erhalten: P
mackycheese21

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 prüft, ob eine Liste ein Palindrom ist.

x!yist, Truewenn sich die Listen xund y(die die gleiche Länge haben sollten) an genau zwei Stellen unterscheiden. Insbesondere, wenn xes sich um eine Permutation von handelt y, wird x!ybestimmt, ob es sich um einen "Swap" handelt.

o nfindet die Dennis-Ordnung von n. Es filtert nach Swaps zwischen den Permutationen von x = show nund zählt dann, wie viele dieser Swaps Palindrome sind. Das Listenverständnis, das diese Zählung durchführt, verfügt über eine zusätzliche Schutzfunktion. Dies not (p x)bedeutet, dass es zurückgegeben wird, 0wenn nes sich zunächst um ein Palindrom handelte.

Das snd (span (<'1') v)Bit ist nur dropWhileein Byte kürzer. es verwandelt sich "01221"in "1221".

fIndizes aus einer Liste von (i, o i)wo o i > 0(dh ieine Dennis Zahl.) Es normalerweise ein Off-by-one Fehler hier wäre, da (!!)zählt von 0 , aber das Problem zählt von 1 gelang es mir , hier Abhilfe zu schaffen , indem die Suche von Start -10(die hat sich in meinem Programm als Dennis-Nummer herausgestellt!) und dabei alle Zahlen an die richtigen Stellen geschoben.

f 774ist (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)

Ich kann mir nicht vorstellen, dass mein Tauschcode besonders optimal ist, aber das ist das Beste, was ich bekommen habe. Mir gefällt auch nicht, wie oft ich zwischen String und Integer konvertiere ...

Für jede Zahl wird eine Liste erstellt, aus der hervorgeht, ob alle zweistelligen Tauschvorgänge Palindrome sind. Der Zähler wird dekrementiert, wenn mindestens einer dieser Werte wahr ist und die ursprüngliche Zahl kein Palindrom ist. Da 0+Truein Python 1die Summe der Endergebnisse ausgewertet wird, arbeitet die Liste in der Reihenfolge der Dennis-Nummer.


5

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

Das neue Java? : /

Ungolfed und kommentiert:

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

Gelee , 33 Bytes (nicht konkurrierend)

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

Probieren Sie es online!

Wie es funktioniert

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

Der Schleifenrumpf gibt einen Vektor mit 4 Zahlen zurück: 1) das von der Eingabe gelesene linke Argument , 2) die Anzahl der bisherigen Dennis-Zahlen, 3) den aktuellen Wert des XSchleifenzählers und 4) Kdie als Summe der Palindrome berechnete Reihenfolge innerhalb von 1-Swap-Permutationen. Es endet, wenn die ersten beiden Elemente gleich werden und die letzten beiden als Ergebnis zurückgegeben werden.


2

JavaScript (ES6), 229

Wie üblich glänzt JavaScript durch seine Unfähigkeit zur Kombinatorik (oder vielleicht ist es meine Unfähigkeit ...). Hier bekomme ich alle möglichen Swap-Positionen, wobei alle Binärzahlen der angegebenen Länge und nur 2 gesetzt sind.

Testen Sie die Ausführung des folgenden Snippets in Firefox (da MSIE nicht mit EcmaScript 6 kompatibel ist und in Chrome noch Standardparameter fehlen).

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}

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
}

Verwendungszweck

Fügen Sie dies in Ihre Konsole ein und ersetzen Sie die Nummer danach echo, wenn Sie möchten

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

Bei höheren Zahlen wird es langsam;)

Ungolfed wiederverwendbare Version

{
    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

Rubin, 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]}

Verwendet die Ruby-Funktion, bei der der Aufruf "19".next!zurückkehrt "20", um zu vermeiden, dass Typen hin und her konvertiert werden müssen. Wir verwenden nur einen regulären Ausdruck, um das Führen zu ignorieren 0s. Durchläuft alle Paare von Zeichenfolgenpositionen, um nach palindromischen Schaltern zu suchen. Ich schrieb dies ursprünglich eine rekursive Funktion, aber es sprengt den Stapel.

Die Ausgabe für 774 ist ["12012", 3](das Entfernen der Anführungszeichen würde 4 weitere Bytes kosten, aber ich denke, die Spezifikation erlaubt es ihnen).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.