Створення Денніса Числа


69

Цей виклик - данина користувачеві PPCG Деннісу за те, що він переміг у частині грабіжників Вікторини мови програмування .

Переглядаючи сторінку профілю PPCG Денніса, ми можемо побачити кілька вражаючих речей:

Профіль Dennis

В даний час він має понад шістдесят вісім тисяч репутації, що робить його другим у складі респ , перевершивши третє місце майже на тридцять тисяч. Нещодавно він переміг на наших виборах за нового модератора і отримав блискучий новий алмаз поруч зі своїм іменем. Але я особисто думаю, що найцікавіша частина Денніса - це його ідентифікаційний номер користувача PPCG: 12012.

На перший погляд 12012майже схожий на паліндром , число, яке читається однакове при переверненні, але воно трохи відключене. Він може стати паліндром, 21012якщо ми поміняємо позиції першого 1і 2, і він може стати паліндром, 12021якщо поміняти останнім 1і 2. Крім того, дотримуючись конвенції про те, що провідні нулі в кількості не записуються, замінюючи перше, 1а 0результати - 02112точніше, 2112є іншим паліндром.

Давайте визначимо число Денніса як додатне ціле число, яке не є самим паліндромним, але може бути перетворене в паліндром, замінивши позиції щонайменше однієї пари з будь-яких двох цифр. Порядок ряду Dennis це число різних пар чисел , які можна поміняти місцями , щоб зробити (не обов'язково різні) паліндром.

Таким чином , порядок 12012дорівнює 3 , починаючи з 3 різними парами його цифр ( 12012, , ) може бути замінено навколо , щоб зробити паліндроми. трапляється найменший порядок 3 номер Денніса.120121201212012

10є найменшим номером Денніса і має порядок 1, оскільки перемикання навколо 1та 0дає 01ака, 1який є паліндром.

Уявні провідні нулі числа не вважаються перемикаються цифрами. Наприклад, зміна 8908в 08908і поміняти місцями перші дві цифри , щоб отримати паліндром 80908недійсний. 8908не номер Денніса.

Можна сказати, що номери Денніса не мають порядку 0.

Виклик

Напишіть програму або функцію, яка приймає натуральне число N та друкує або повертає N-е найменше число Денніса разом із його порядком у певному розумному форматі, наприклад, 12012 3або (12012, 3).

Наприклад, 12012це номер 774-го Денніса, тому, якщо 774це вхід до вашої програми, вихід повинен бути чимось подібним 12012 3. (Цікаво, що 774 - це ще одне число Денніса.)

Виграє найкоротший код у байтах.

Ось перші 20 номерів Денніса та їх доручення:

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

Ось такий самий список до N = 1000.


31
До цього слід додати OEIS
Claudiu

28
@Claudiu це буде додано до OEIS.
user48538

Відповіді:


13

Pyth, 44 байти

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

Спробуйте в Інтернеті: Демонстрація або Тестовий набір

Дурний баг (?) У Pyth зіпсував рішення на 41 байт.

Пояснення:

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

А що це за «дурний клоп (?)»
CalculatorFeline

@CatsAreFluffy Довелося шукати історію Github. Це стосується .f. Ось запит на притягнення, який я зробив через це питання: github.com/isaacg1/pyth/pull/151
Jakube

42

CJam, 45 байт

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

Спробуйте в Інтернеті!

Як це працює

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
Я вже натиснув реп-коп, але мені довелося опублікувати першу відповідь.
Денніс

1
Тьфу. Як змусити себе прийняти коментар із 42 заявами?
NieDzejkob

Я отримав 42-й підсумок: P
mackycheese21

7

Haskell, 174 байт

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 перевіряє, чи є список паліндром.

x!yє Trueтоді і тільки тоді списки xі y(які повинні мати однакову довжину) відрізняються рівно в два місця. Зокрема, якщо xце перестановка y, x!yвизначає, чи є це "свопом".

o nзнаходить орден Денніса n. Він фільтрує для свопів серед перестановок x = show n, а потім підраховує, скільки з цих свопів є паліндромами. Зрозуміння списку, яке виконує цей підрахунок, має додатковий захист not (p x), а це означає, що він повернеться, 0якщо для цього nбув паліндром.

snd (span (<'1') v)Біт просто , dropWhileале один байт коротше; вона перетворюється "01221"на "1221".

fіндекси зі списку, (i, o i)де o i > 0(тобто iчисло Денніса.) Тут зазвичай виникає помилка по одному, яка (!!)вважається від 0, але проблема нараховується від 1. Мені вдалося виправити це, запустивши пошук -10(з якого моєю програмою виявилося число Денніса!), тим самим висунувши всі числа в потрібні місця.

f 774є (12012,3).


6

Пітон 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)

Я не можу уявити, що мій код обміну є особливо оптимальним, але це найкраще, що я міг отримати. Мені також не подобається, як часто я конвертую між рядком і цілим числом ...

Для кожного числа воно створює перелік того, чи всі підміни двох цифр є паліндрами. Він зменшує лічильник, коли принаймні одне з цих значень відповідає істині, а початкове число не є паліндром. Оскільки 0+Trueв python оцінює до 1суми остаточного списку працює для порядку числа Денніса.


5

Іржа, 390 байт

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

Негольфірованний і прокоментував:

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

Желе , 33 байти (не конкуруючий)

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

Спробуйте в Інтернеті!

Як це працює

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

Тіло циклу повертає вектор із 4 чисел: 1) його лівий аргумент, прочитаний з введення, 2) підрахунок чисел Денніса до цього часу, 3) поточне значення X- лічильник циклу, і 4) його порядок, Kобчислений як сума паліндром в рамках перестановок 1-swap. Він припиняється, коли перші два елементи стають рівними, а останні два повертаються в результаті.


2

JavaScript (ES6), 229

Як завжди, JavaScript світить своєю незмінністю для комбінаторики (або, можливо, це моя невмілість ...). Тут я отримую всі можливі положення підкачки, знаходячи всі двійкові числа заданої довжини та лише 2 встановлені.

Тест запустіть фрагмент нижче у Firefox (оскільки MSIE далеко не сумісний з EcmaScript 6, а в Chrome досі відсутні параметри за замовчуванням)

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}

Будова

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

Використання

Вставте це на консоль і замініть номер після echo, якщо хочете

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

Це стає повільним при більшій кількості;)

Версія для неодноразового використання для багаторазового використання

{
    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

Рубі, 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]}

Використовує функцію Ruby, коли виклик "19".next!повертається, "20"щоб уникнути необхідності перетворення типів вперед і назад; ми просто використовуємо регулярний вираз, щоб ігнорувати ведучі 0s. Ітератує над усіма парами рядкових рядків, щоб перевірити наявність паліндромних комутаторів. Я спочатку писав цю рекурсивну функцію, але вона перетворює стек.

Вихід 774 є ["12012", 3](видалення лапок обійдеться ще на 4 байти, але, думаю, специфікація їх дозволяє).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.