Генерировать числа Денниса

69

Эта задача - дань уважения пользователю PPCG Деннису за победу в грабительской части Викторины по языку программирования .

Глядя на страницу профиля Денниса PPCG, мы можем увидеть довольно впечатляющие вещи:

Денис профиль

В настоящее время у него более шестидесяти восьми тысяч репутации, что делает его вторым по репутации , превосходя третье место почти на тридцать тысяч. Недавно он выиграл наши выборы нового модератора и получил новый блестящий бриллиант рядом с его именем. Но лично я думаю, что самая интересная часть о Деннисе - это его идентификационный номер пользователя 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)]
Jakube
источник
И что это за «глупый маленький баг (?)»
CalculatorFeline
@CatsAreFluffy Пришлось посмотреть историю Github. Это касается .f. Вот запрос на извлечение, который я сделал из-за этого вопроса: github.com/isaacg1/pyth/pull/151
Якуб
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-е upvote: 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находит Dennis-порядок 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

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)

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

Для каждого числа создается список того, являются ли все перестановки из двух цифр палиндромами. Счетчик уменьшается, когда хотя бы одно из этих значений истинно, а исходное число не является палиндромом. Так как 0+Trueв python вычисляется 1сумма итогового списка работ для порядка числа Денниса.

FryAmTheEggman
источник
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-перестановок. Он заканчивается, когда первые два элемента становятся равными, а последние два возвращаются как результат.

user44932
источник
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>

edc65
источник
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}'

Это становится медленным при больших числах;)

Ungolfed многоразовая версия

{
    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
источник
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 байта больше, но я думаю, что спецификация позволяет им).

histocrat
источник