Números de Dennis 2.0

54

Usuário PPCG e mod eleito, @Dennis acabou de se tornar o segundo usuário a ganhar mais de 100k repetições!

insira a descrição da imagem aqui

Essa é uma ideia totalmente original, que eu não recebi de mais ninguém , mas vamos fazer um desafio baseado em seu ID de usuário, 12012como uma homenagem!

Olhando para ele, você notará que existem duas "seções" distintas no ID dele.

12

e

012

Ambas as seções somam 3. Isso é uma propriedade bastante interessante.

Vamos definir um "número Dennis 2.0" como qualquer número inteiro positivo em que toda subsequência máxima de dígitos estritamente crescentes seja igual ao mesmo número. Por exemplo,

123

é um número Dennis 2.0 porque existe apenas uma sub-lista máxima de dígitos estritamente crescentes e soma 6. Além disso, 2.846.145 também é um número Dennis 2.0 porque as três sublistas máximas de dígitos crescentes, a saber

28
46
145

Tudo soma para 10. Além disso, os números que apenas repetem o mesmo dígito devem ser números Dennis 2.0, porque, por exemplo, 777podem ser divididos em

7
7
7

que claramente todos somam sete.

Um número que não42 seja o número Dennis 2.0, pois é dividido em

4
2

que claramente não somam o mesmo número.

O desafio

Você deve escrever um programa ou função para determinar se um determinado número é um número Dennis 2.0 ou não. Você pode obter entrada e saída em qualquer formato de entrada razoável, por exemplo, como uma string, como um número, de um arquivo, argumentos / retorno de função, de STDIN / STDOUT, etc. e, em seguida, retornar um valor verdadeiro se esse número for um Dennis 2.0 número e um valor falso se não for. Para referência, eis todos os números do Dennis 2.0 de até 1.000:

1
2
3
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
22
23
24
25
26
27
28
29
33
34
35
36
37
38
39
44
45
46
47
48
49
55
56
57
58
59
66
67
68
69
77
78
79
88
89
99
101
111
123
124
125
126
127
128
129
134
135
136
137
138
139
145
146
147
148
149
156
157
158
159
167
168
169
178
179
189
202
222
234
235
236
237
238
239
245
246
247
248
249
256
257
258
259
267
268
269
278
279
289
303
312
333
345
346
347
348
349
356
357
358
359
367
368
369
378
379
389
404
413
444
456
457
458
459
467
468
469
478
479
489
505
514
523
555
567
568
569
578
579
589
606
615
624
666
678
679
689
707
716
725
734
777
789
808
817
826
835
888
909
918
927
936
945
999

As brechas padrão se aplicam e a resposta mais curta, medida em bytes, vence!

DJMcMayhem
fonte
11
Apenas para referência, Martin Ender foi o primeiro a obter 100k rep.
Erik the Outgolfer
11
12366 é um número 2.0 válido? (123 | 6 | 6 vs. 1236 | 6)
Sp3000
2
@ sp3000 Esse não é um número Dennis. Seria1236|6
DJMcMayhem
Posso pegar cada dígito, pois é uma representação unária com um ,entre eles? Provavelmente isso está exagerando bastante.
Riley
13
Im medo Dennis irá destruir todos nós neste desafio nontheless
downrep_nation

Respostas:

15

Geléia, 13 12 bytes

1 byte graças a @Dennis.

DIṠ’0;œṗDS€E

Experimente online!

Explicação

DIṠ’0;œṗDS€E    Main link. Argument: N
D               Convert N to its digits.
 I              Find the differences between the elements.
  Ṡ             Find the sign of each difference. This yields 1 for locations where the
                list is strictly increasing and 0 or -1 elsewhere.
   ’            Decrement. This yields 0 for locations where the list is strictly
                increasing and -1 or -2 elsewhere.
    0;          Prepend a 0.
        D       Get another list of digits.
      œṗ        Split the list of digits at truthy positions, i.e. the -1s and -2s.
         S€     Sum each sublist.
           E    Check if all values are equal.
PurkkaKoodari
fonte
16

JavaScript (ES6), 72 70 bytes

Toma uma string como entrada. Retorna um valor falso ou verdadeiro (que pode ser um número).

Está usando uma expressão regular para transformar uma sequência de entrada, como "2846145"em:

"(a=2+8)&&(a==4+6)&&(a==1+4+5)"

Então chama eval()essa expressão.

let f =

n=>eval(n.replace(/./g,(v,i)=>(v>n[i-1]?'+':i?')&&(a==':'(a=')+v)+')')

console.log(f("101"));
console.log(f("102"));
console.log(f("777"));
console.log(f("2846145"));

Arnauld
fonte
Bom, é uma ideia muito inteligente. :-)
ETHproductions
Também gosto dessa ideia! Mas isso não está funcionando: console.log (f ("2011")); // falso console.log (f ("189")); // 18
user470370
3
@ user470370 - acho que está realmente correto. A definição declara "subsequências de números estritamente crescentes" , portanto, se 2011divide como 2 / 01 / 1e não é um número D2.0. Quanto a 189, é um número D2.0 e 18é um valor verdadeiro.
Arnauld
Ups course Claro, você está certo. Não entendi isso antes. Eu acho que tenho que refazer minha própria solução: D
user470370
15

Python, 50 bytes

r='0'
for d in input():r=d+'=+'[r<d]*2+r
1/eval(r)

Espera input()avaliar uma string, para que a entrada precise de aspas no Python 2. A saída é via código de saída , em que 0 indica sucesso (verdade) e 1 indica falha (falsidade).

Teste em Ideone .

Como funciona

Inicializamos r na string 0 e iteramos sobre todos os dígitos d na entrada.

  • Se d for maior que o primeiro dígito de r (inicialmente 0 , então igual ao valor anterior de d ), r<davaliará como Verdadeiro e '=+'[r<d]*2renderá ++.

  • Se d for menor que o primeiro dígito de r , será '=+'[r<d]*2gerado ==.

  • Se d for igual ao primeiro dígito de r , r será maior que a sequência singleton d , portanto, '=+'[r<d]*2produzirá novamente ==.

Em todos os casos, o dígito d e os dois caracteres gerados são anexados a r .

Depois que todos os dígitos de entrada foram processados, eval(r)avalia a expressão gerada.

  • Se a entrada consistir em uma única sequência estritamente crescente de dígitos (positivos), a expressão será avaliada como sua soma.

    Por exemplo, o número inteiro 12345 resulta na expressão 5++4++3++2++1++0, que gera 15 quando avaliada. Observe que cada segundo + é uma vantagem unária , portanto não afeta o resultado. Dividir 1 por 15 é válido (o resultado não é importante); o programa sai normalmente.

  • Se a entrada consistir em duas seqüências estritamente crescentes de dígitos, a expressão consistirá em uma comparação simples.

    Por exemplo, o número inteiro 12012 resulta na expressão 2++1++0==2++1++0, que produz True quando avaliado, pois os dois termos possuem a soma 3 . Dividir 1 por Verdadeiro ( 1 ) é válido (o resultado não é importante); o programa sai normalmente.

    Por outro lado, o número inteiro 12366 resulta na expressão 6==6++3++2++1++0, que gera Falso quando avaliado, pois os termos têm as somas 6 e 12 . Dividir 1 por False ( 0 ) gera um ZeroDivisionError ; o programa sai com um erro.

  • Se a entrada consistir em três ou mais sequências estritamente crescentes de dígitos, a expressão consistirá em uma comparação encadeada , que retornará True se e somente se todas as comparações envolvidas retornarem True .

    Por exemplo, o número inteiro 94536 resulta na expressão 6++3==5++4==9++0, que gera True quando avaliado, pois todos os termos têm soma 9 . Como antes, o programa sai normalmente.

    Por outro lado, o número inteiro 17263 resulta na expressão 3==6++2==7++1++0, que produz False quando avaliada, pois os termos possuem as somas 3 , 8 e 8 . Como antes, o programa sai com um erro.

Dennis
fonte
11
Sobre o tempo que eu postei uma submissão a este desafio ...
Dennis
7

Braquilog , 13 bytes

~c@e:{<+}a!#=

Experimente online!

Explicação

~c               Find a list of integers which when concatenated result in the Input
  @e             Split the integers into lists of digits
    :{<+}a       Each list of digit is stricly increasing, and compute its sum
          !      Discard all other choice points (prevents backtracking for smaller sublists)
           #=    All sums must be equal

~c unificar-se-á primeiro com os maiores sublistas.

Fatalizar
fonte
6

Pyke, 18 bytes

mb$1m>0R+fMbms}lt!

Experimente aqui!

mb                 -         map(int, input)
  $                -        delta(^)
   1m>             -       map(^, 1>i)
      0R+          -      [0]+^
         f         -     input.split_at(^) 
          Mb       -    deep_map(int, ^)
            ms     -   map(sum, ^)
              }    -  uniquify(^)
               lt! - len(^) == 1
Azul
fonte
6

PowerShell v2 +, 100 64 61 bytes

-join([char[]]$args[0]|%{("+$_","-eq$_")[$_-le$i];$i=$_})|iex

Um one-liner literal, pois esse é o único canal. Recebe a entrada como uma sequência $args[0]. charFaz um loop através dele como uma matriz, cada iteração colocando o elemento atual com um +ou -eqà frente dele no pipeline com base em se o valor atual é -less ou than equal ao valor anterior $i. Essas seqüências de caracteres são -joineditadas juntas e canalizadas para iex(abreviação Invoke-Expressione semelhante a eval. Por exemplo, para entrada, 2846145isso será avaliado como +2+8-eq4+6-eq1+4+5, o que é True.

Esse booleano é deixado no pipeline e True/ Falseé implicitamente gravado na conclusão do programa.

NB - para entrada com um dígito, o dígito resultante é deixado no pipeline, que é um valor verdadeiro no PowerShell.

Exemplos

PS C:\Tools\Scripts\golfing> 2846145,681,777,12366,2|%{"$_ -> "+(.\dennis-number-20.ps1 "$_")}
2846145 -> True
681 -> False
777 -> True
12366 -> False
2 -> 2
AdmBorkBork
fonte
6

GNU sed 217 ou 115

Ambos incluem +1 para -r

217:

s/./&,/g;s/^/,/g;:;s,0,,;s,2,11,;s,3,21,;s,4,31,;s,5,41,;s,6,51,
s,7,61,;s,8,71,;s,9,81,;t;s/(,1*)(1*)\1,/\1\2X\1,/;t;s/,//g
s,1X1(1*),X\1a,;t;/^1.*X/c0
/Xa*$/s,a*$,,;y,a,1,;/1X1/b;/1X|X1/c0
c1

Aceita entrada em decimal normal

Experimente online!


115:

s/^|$/,/g;:;s/(,1*)(1*)\1,/\1\2X\1,/;t;s/,//g
s,1X1(1*),X\1a,;t;/^1.*X/c0
/Xa*$/s,a*$,,;y,a,1,;/1X1/b;/1X|X1/c0
c1

Recebe a entrada como uma lista separada por vírgula dos dígitos dos números em unário. por exemplo, 123seria1,11,111

Experimente online!

Riley
fonte
5

Perl, 38 + 3 ( -p) = 41 bytes

-9 bytes graças a @Ton Hospel !

s%.%2x$&.(~$&le~$')%eg;$_=/^(2+1)\1*$/

Como existe um $', o código precisa estar em um arquivo para ser executado. Então -pconta para 3 bytes. Gera 1 se o número for um número Dennis 2.0 ou uma sequência vazia, caso contrário:

$ cat dennis_numbers.pl
s%.%2x$&.(~$&le~$')%eg;$_=/^(2+1)\1*$/
$ perl -p dennis_numbers.pl <<< "1
10
12315
12314"
dada
fonte
11
Eu acho que esta é provavelmente a melhor abordagem em perl, mas você pode golfe lo para baixo para 42: s%.%2x$&.($&.O ge$')%eg;$_=/^(2+1)\1*$/com a -popção (+3 porque o código tem $')
Ton Hospel
De fato, usar o resultado da comparação em vez dessa aleatória Aé muito melhor! Obrigado! Mas eu não entendo .O... Sem ele, ele falha em alguns casos, mas não consigo entender o porquê.
Dada
$'é o próximo dígito e todos os seguintes. Então, por exemplo, 778ele se compara 7ao 78qual se ltparece com uma sequência crescente. As Oquebras e que se comparam 7Oa 78 (qualquer coisa acima 9em ASCII funciona)
Ton Hospel 30/09/16
Oh certo, isso é legal! Eu procurei uma maneira de usar $' or $`em vez dos meus grupos de captura, mas não consegui encontrá-lo, por causa disso" e todos os que estão atrás dele ". Obrigado pela dica!
Dada
Mmm, ~$&le~$'deve ser 1 mais curto
Ton Hospel 30/09/16
5

JavaScript (ES6), 66 65 63 bytes

Guardado 2 bytes graças a @ edc65

x=>[...x,p=t=z=0].every(c=>p>=(t+=+p,p=c)?(z?z==t:z=t)+(t=0):1)

Recebe a entrada como uma sequência. Versão antiga (funciona apenas no Firefox 30 ou superior):

x=>[for(c of(p=t=0,x))if(p>=(t+=+p,p=c))t+(t=0)].every(q=>q==+p+t)
ETHproductions
fonte
Dica: [...x,0]->[...x,p=t=z=0]
edc65
@ edc65 Obrigado, eu não tinha pensado nisso!
ETHproductions
3

Mathematica, 38 bytes

Equal@@Tr/@IntegerDigits@#~Split~Less&

Função anônima. Pega um número como entrada e retorna Trueou Falsecomo saída.

LegionMammal978
fonte
3

Braquilog 2, 10 bytes, desafio de pós-datas de idiomas

ẹ~c<₁ᵐ!+ᵐ=

Experimente online!

Esse é basicamente o mesmo algoritmo da resposta de @ Fatalize (que eu não vi até depois de ter escrito isso), mas reorganizado um pouco para torná-lo mais eficiente sob a sintaxe do Brachylog 2.

É um programa completo, retornando false.se não for um número do Dennis 2.0 ou truese for.

Explicação

ẹ~c<₁ᵐ!+ᵐ=
ẹ           Interpret the input number as a list of digits
      !     Find the first (in default order)
 ~c           partition of the digits
   <₁ᵐ        such that each is in strictly increasing order
         =  Assert that the following are all equal:
       +ᵐ     the sums of each partition

Como sempre, para um programa completo do Brachylog, se todas as asserções puderem ser cumpridas simultaneamente, obtemos um retorno verdadeiro, caso contrário, falsey. A ordem padrão para ~cé classificar partições com menos elementos mais longos primeiro e, no Prolog (portanto, Brachylog), a ordem padrão definida pelo primeiro predicado no programa (usando o segundo como um desempate etc.); aqui, ~cdomina, porque é determinista e, portanto, não tem nada para pedir).


fonte
2

MATL, 24 23 20 18 16 bytes

Tjdl<vYsG!UlXQ&=

Retorna uma verdade de matriz falsey

Experimente Online!

Além disso, parabéns @Dennis!

Explicação

T       % Push a literal TRUE to the stack
        %   STACK: {1}
j       % Explicitly grab the input as a string
        %   STACK: {1, '2846145'}
d       % Compute the difference between successive ASCII codes
        %   STACK: {1, [6 -4 2 -5 3 1]}
l<      % Find where that difference is less than 1
        %   STACK: {1, [0 1 0 1 0 0]}
v       % Prepend the TRUE value we pushed previously
        %   STACK: {[1 0 1 0 1 0 0]}
Ys      % Compute the cumulative sum. This assigns a unique integer label to
        % each set of increasing numbers
        %   STACK: {[1 1 2 2 3 3 3]}
G!U     % Grab the input as numeric digits
        %   STACK: {[1 1 2 2 3 3 3], [2 8 4 6 1 4 5]}
lXQ     % Compute the sum of each group of increasing digits
        %   STACK: {[10 10 10]}
&=      % Computes element-wise equality (automatically broadcasts). A
        % truthy value in MATL is a matrix of all ones which is only the case
        % when all elements are equal:
        %   STACK: {[1 1 1
        %            1 1 1
        %            1 1 1]}
        % Implicitly display the result
Suever
fonte
Bom uso de &=!
Luis Mendo
2

PHP, 108 105 92 bytes

$p=-1;foreach(str_split("$argv[1].")as$d)$p>=$d?$r&&$s-$r?die(1):($r=$s)&$s=$p=$d:$s+=$p=$d;

recebe entrada do argumento, sai com 0para o número Dennis-2.0, com 1else.

demolir

$p=-1;                              // init $p(revious digit) to -1
foreach(str_split("$argv[1].")as$d) // loop $d(igit) through input characters
                                    // (plus a dot, to catch the final sum)
    $p>=$d                              // if not ascending:
        ?$r                             // do we have a sum remembered 
        &&$s-$r                         // and does it differ from the current sum?
                ?die(1)                     // then exit with failure
                :($r=$s)&$s=$p=$d           // remember sum, set sum to digit, remember digit
        :$s+=$p=$d                      // ascending: increase sum, remember digit
    ;
// 
Titus
fonte
2

05AB1E , 18 bytes

SD¥X‹X¸«DgL*ꥣOÙg

Explicação

N = 12012 usado como exemplo.

                    # implicit input N = 12012
S                   # split input number to list of digits  
                    # STACK: [1,2,0,1,2]
 D                  # duplicate
                    # STACK: [1,2,0,1,2], [1,2,0,1,2]
  ¥                 # reduce by subtraction
                    # STACK: [1,2,0,1,2], [1,-2,1,1]
   X‹               # is less than 1
                    # STACK: [1,2,0,1,2], [0,1,0,0]
     X¸«            # append 1
                    # STACK: [1,2,0,1,2], [0,1,0,0,1]
        DgL*        # multiply by index (1-indexed)
                    # STACK: [1,2,0,1,2], [0,2,0,0,5]
            ê       # sorted unique
                    # STACK: [1,2,0,1,2], [0,2,5]
             ¥      # reduce by subtraction
                    # STACK: [1,2,0,1,2], [2,3]
              £     # split into chunks
                    # STACK: [[1,2],[0,1,2]]
               O    # sum each
                    # STACK: [3,3]
                Ù   # unique
                    # STACK: [3]
                 g  # length, 1 is true in 05AB1E
                    # STACK: 1

Experimente online!

Emigna
fonte
2

Ruby 2.3, 56 bytes

p !gets.chars.chunk_while(&:<).map{|a|eval a*?+}.uniq[1]

Quase certamente não é a maneira mais divertida de fazer isso, mas mostra alguns recursos interessantes de linguagem.

(Não é tolerante a novas linhas, execute como ruby dennis2.rb <<< '12012')

histocrata
fonte
1

PHP, 144 bytes

<?php preg_match_all("/0?1?2?3?4?5?6?7?8?9?/",$argv[1],$n);foreach($n[0]as$i)if(strlen($i)&&($a=array_sum(str_split($i)))!=$s=$s??$a)die;echo 1;

Tenho certeza de que há uma maneira muito mais inteligente (e mais curta) de fazer isso, mas servirá por enquanto.

user59178
fonte
1

Python 2, 69 bytes

Recebe a entrada como uma sequência.

lambda I:len(set(eval(reduce(lambda x,y:x+',+'[y>x[-1]]+y,I+' '))))<2

Explicação:

ex 1201212012

Converte em lista de somas:

1+2,0+1+2,1+2,0+1+2,

Avalia e converte para definir.

set([3])

Se o comprimento do conjunto for 1, todas as somas serão iguais.

TFeld
fonte
1

JavaScript (ES6), 58

s=>![...s,z=x=p=0].some(c=>[c>p?0:z-=(x=x||z),z-=p=c][0])

Aplicando minha dica raramente útil https://codegolf.stackexchange.com/a/49967/21348

Ele verifica a string char por char, identificando a sequência de caracteres ascendentes; no final de cada rum, verifica se a soma é sempre a mesma

  • c: caractere atual
  • p: caractere anterior
  • z: soma de execução, no final de uma execução será comparada com ...
  • x: soma para comparar, na primeira execução é simplesmente igual a z

Teste

f=
s=>![...s,z=x=p=0].some(c=>[c>p?0:z-=(x=x||z),z-=p=c][0])

function run()
{
  var i=I.value
  O.textContent = i + ' -> ' + f(i)
}

run()

test=`1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 22 23 24 25 26 27 28 29 33 34 35 36 37 38 39 44 45 46 47 48 49 55 56 57 58 59 66 67 68 69 77 78 79 88 89 99 101 111 123 124 125 126 127 128 129 134 135 136 137 138 139 145 146 147 148 149 156 157 158 159 167 168 169 178 179 189 202 222 234 235 236 237 238 239 245 246 247 248 249 256 257 258 259 267 268 269 278 279 289 303 312 333 345 346 347 348 349 356 357 358 359 367 368 369 378 379 389 404 413 444 456 457 458 459 467 468 469 478 479 489 505 514 523 555 567 568 569 578 579 589 606 615 624 666 678 679 689 707 716 725 734 777 789 808 817 826 835 888 909 918 927 936 945 999`.split` `

numerr=0
for(i=1; i<1000; i++)
{
  v = i + '';
  r = f(v);
  ok = r == (test.indexOf(v) >= 0)
  if (!ok) console.log('Error',++numerr, v)
}  
if(!numerr) console.log('All test 1..999 ok')
<input id=I value=612324 type=number oninput='run()'>
<pre id=O>

edc65
fonte
0

Rubi, 117 105 85 bytes

# original (117):
j,k=0,?0;"#{i}".chars.group_by{|n|n>k||j=j+1;k=n;j}.values.map{|a|a.map(&:to_i).reduce(&:+)}.reduce{|m,n|n==m ?m:nil}

# inspired by PHP regexp approach (105):
"#{i}".scan(/0?1?2?3?4?5?6?7?8?9?/).map{|a|a.chars.map(&:to_i).reduce(&:+)}.reduce{|m,n|!n||n==m ?m:nil}

# some number comparison simplification (85):
!"#{i}".scan(/0?1?2?3?4?5?6?7?8?9?/).map{|a|a.chars.map(&:to_i).reduce(&:+)}.uniq[1]

Isso retornaria o número inteiro desse número de dennis ou, nilse não, um número de dennis. Todos os números inteiros serão considerados verdadeiros em ruby ​​e também serão nilconsiderados falsos. ié o número inteiro que está sendo verificado.

Terceira versão realmente retorna truee false.

PS testado para retornar 172 números inteiros de 1 a 1000, como na resposta.

akostadinov
fonte
0

APL, 23 bytes

{1=≢∪+/↑N⊂⍨1,2>/N←⍎¨⍕⍵}

Explicação:

  • N←⍎¨⍕⍵: obter os dígitos individuais na entrada, armazenar em N
  • N⊂⍨1,2>/N: encontre as sublistas de números estritamente crescentes em N
  • +/↑: soma cada sublist
  • 1=≢∪: veja se a lista resultante possui apenas um elemento exclusivo
marinus
fonte
0

Adicione ++ , 109 bytes

D,g,@@#,BF1_B
D,k,@@#,bR$d@$!Q@BFB
D,f,@,BDdVÑ_€?1€_0b]$+€?dbLRBcB*BZB]GbL1+b]+qG€gd€bLÑ_0b]$+BcB]£k€¦+Ñ=1$ª=

Experimente online!

Como funciona

fgkf

f(x)

x1[4,4,4]0110A010

[1,2,...length(A)]0AAAAA

ggA

g(x,y)

g(x,y)x:=[1,2,0,1,2]y=33AA10x=12012A=[3,6]3A6x

g([1,2,0,1,2],3)[1 2 0 1 2 2][1,2]g

g(x,y)yAx:=12012g

[[[1 2] [1 2 0 1 2]]]

[2,5]A10[0,3]gB

k(x,n)

k[[1,2],[3,4],[5,6]]

[[[1,2],0],[[1,2,0,1,2],3]]kk([1,2,0,1,2],3)

k(x,n)gn=0[n,x,n]n=0[[2,1,0,1,2],3]nxxB

[0,1,2][2,1,0]

k(x,n)(x,n)B1


fonte