Numaramda art arda kaç tane azalan sayı var?


18

2019 geldi ve muhtemelen herkes bu sayının tuhaflığını fark etti: aslında bir dizi ardışık azalan sayıyı temsil eden iki alt sayıdan (20 ve 19) oluşur.

Meydan okuma

Bir sayı verildiğinde x, alt sayıları alınarak oluşturulabilecek maksimum ardışık, azalan sayı dizisinin uzunluğunu döndürün x.

Notlar:

  • alt sayılar (örn baştaki sıfırları içeremez 1009bölünebilir olamaz 10, 09)
  • ardışık ve azalan, dizideki bir sayının önceki -1 veya nben+1=nben-1 eşit olması gerektiği anlamına gelir (örneğin 52, 5,2çünkü bölünemez 5ve 2ardışık değildir, 2 ≠ 5 - 1)
  • dizisi içinde örneğin tam numarasını kullanarak elde edilmelidir 7321gözardı edemeyiz size 7ve diziyi olsun 3, 2,1
  • sadece tek bir sıra numarası elde edilebilir, örneğin 3211098iki dizi yarık olamaz 3, 2, 1ve 10, 9,8

Giriş

  • Bir tam sayı ( >= 0): bir sayı, bir dize veya rakam listesi olabilir

Çıktı

  • Maksimum azalan alt sayı sayısı verilen tek bir tamsayı (bu sayının alt sınırının 1, yani bir sayının kendisinin uzunluğu bir azalan sırada olduğunu unutmayın)

Örnekler:

2019         --> 20,19           --> output : 2
201200199198 --> 201,200,199,198 --> output : 4
3246         --> 3246            --> output : 1
87654        --> 8,7,6,5,4       --> output : 5
123456       --> 123456          --> output : 1
1009998      --> 100,99,98       --> output : 3
100908       --> 100908          --> output : 1
1110987      --> 11,10,9,8,7     --> output : 5
210          --> 2,1,0           --> output : 3
1            --> 1               --> output : 1
0            --> 0               --> output : 1
312          --> 312             --> output : 1
191          --> 191             --> output : 1

Genel kurallar:

  • Bu , bayt en kısa cevap kazanır.
    Kod golf dillerinin, kod yazmayan dillerle yanıt göndermenizi engellemesine izin vermeyin. Herhangi bir programlama dili için mümkün olduğunca kısa bir cevap bulmaya çalışın.
  • Varsayılan I / O kuralları ile cevabınız için standart kurallar geçerlidir , bu nedenle STDIN / STDOUT, fonksiyonlar / yöntem uygun parametreler ve dönüş tipi, tam programlar ile kullanılabilir. Çağrınız.
  • Varsayılan Loopholes yasaktır.
  • Mümkünse, lütfen kodunuz için bir test içeren bir bağlantı ekleyin (örn. TIO ).
  • Ayrıca, cevabınız için bir açıklama eklemeniz şiddetle tavsiye edilir.

1
Korumalı alandan
taşındı

1
Test durumu 210 -> 2,1,0yanlış mı (ile aynı 0 -> 0)? Görevler " alt numaralar baştaki sıfırları içeremez " diyor , sıfır özel bir durum mu?
ბიმო

2
@BMO: iyi, burada konu ... tür phylosofical edilir: bana Ge, 0 sıfır (yararsız) rengi olmayan bir sayı, yani evet sıfır özel bir durum olduğunu
digEmAll

2
bunlara ... küçümseyen sayılar diyebilir misiniz ? xD üzgünüm bile komik değildi
HyperNeutrino

Üzgünüm, hakkında sorduğum yorumu sildim 212019. Bütün kuralları okumadım.
siklaminist

Yanıtlar:


6

Jöle ,  15  9 bayt

Dennis sayesinde bugfix

ŻṚẆDfŒṖẈṀ

Çevrimiçi deneyin! (321kod en azÖ(N-2) olduğundan yarım dakika sürer)

Nasıl?

ŻṚẆDfŒṖẈṀ - Link: integer, n
Ż         - [0..n]
 Ṛ        - reverse
  Ẇ       - all contiguous slices (of implicit range(n)) = [[n],...,[2],[1],[0],[n,n-1],...,[2,1],[1,0],...,[n,n-1,n-2,...,2,1,0]]
   D      - to decimal (vectorises)
     ŒṖ   - partitions of (implicit decimal digits of) n
    f     - filter discard from left if in right
       Ẉ  - length of each
        Ṁ - maximum

6

JavaScript (ES6), 56 bayt

ArBo'nun Python cevabının bir limanı önemli ölçüde daha kısadır. Ancak, çok fazla özyineleme nedeniyle bazı test durumlarında başarısız olur.

f=(n,a=0,c=0,s)=>a<0?f(n,a-~c):n==s?c:f(n,--a,c+1,[s]+a)

Çevrimiçi deneyin!


JavaScript (ES6), 66 bayt

Girişi dize olarak alır.

f=(s,n=x='',o=p=n,i=0)=>s[i++]?o==s?i:f(s,--n,o+n,i):f(s,p+s[x++])

Çevrimiçi deneyin!

Yorumlananlar

f = (               // f = recursive function taking:
  s,                //   s = input number, as a string
  n =               //   n = counter
  x = '',           //   x = position of the next digit to be added to p
  o = p = n,        //   o = generated output; p = prefix
  i = 0             //   i = number of consecutive descending numbers
) =>                //
  s[i++] ?          // increment i; if s[i] was defined:
    o == s ?        //   if o is matching s:
      i             //     stop recursion and return i
    :               //   else:
      f(            //     do a recursive call with:
        s,          //       s unchanged
        --n,        //       n - 1
        o + n,      //       (n - 1) appended to o
        i           //       i unchanged (but it was incremented above)
      )             //     end of recursive call
  :                 // else:
    f(              //   this is a dead end; try again with one more digit in the prefix:
      s,            //     s unchanged
      p + s[x++]    //     increment x and append the next digit to p
    )               //   end of recursive call


5

Perl 6 , 43 41 40 bayt

Nwellnhof sayesinde -1 bayt

{/(<-[0]>.*?|0)+<?{[==] 1..*Z+$0}>/;+$0}

Çevrimiçi deneyin!

Regex tabanlı çözüm. Bunun yerine azalan bir listeden daha iyi bir yol bulmaya çalışıyorum, ancak Perl 6 bölümleri iyi yapmıyor

Açıklama:

{                                        }  # Anonymous code block
 /                                /;        # Match in the input
   <-[0]>.*?      # Non-greedy number not starting with 0
            |0    # Or 0
  (           )+  # Repeatedly for the rest of the number
                <?{             }>  # Where
                        1..*Z+$0       # Each matched number plus the ascending numbers
                                       # For example 1,2,3 Z+ 9,8,7 is 10,10,10
                   [==]                # Are all equal
                                    +$0  # Return the length of the list


4

Piton 3 , 232 228 187 181 180 150 149 bayt

@ Jonathan Frech sayesinde -1

e=enumerate
t=int
h=lambda n,s=1:max([1]+[i-len(n[j:])and h(n[j:],s+1)or s+1for j,_ in e(n)for i,_ in e(n[:j],1)if(t(n[:j])-t(n[j:j+i])==1)*t(n[0])])

Çevrimiçi deneyin!

İlk çözülmemiş kod:

def count_consecutives(left, right, so_far=1):
    for i,_ in enumerate(left, start=1):
        left_part_of_right, right_part_of_right = right[:i], right[i:]
        if (int(left) - int(left_part_of_right)) == 1:
            if i == len(right):
                return so_far + 1
            return count_consecutives(left_part_of_right, right_part_of_right, so_far + 1)
    return so_far

def how_many_consecutives(n):
    for i, _ in enumerate(n):
        left, right = n[:i], n[i:]
        for j, _ in enumerate(left, start=1):            
            left_part_of_right = right[:j]
            if int(left) - int(left_part_of_right) == 1 and int(n[i]) > 0:     
                return count_consecutives(left, right)
    return 1

1
s+1 forolabilir s+1for, (t(n[:j])-t(n[j:j+i])==1)*t(n[0])olabilir t(n[:j])-t(n[j:j+i])==1>=t(n[0]).
Jonathan Frech

Görünüşe göre ikinci öneri bir şey getirmeyecek olsa da işe yaramıyor çünkü o zaman ifadeyi ayırmak için alana ihtiyacınız var if.
Nishioka

Doğru ... alternatif 149 .
Jonathan Frech

4

Python 2 , 78 74 73 bayt

l=lambda n,a=0,c=0,s="":c*(n==s)or a and l(n,a-1,c+1,s+`a-1`)or l(n,a-~c)

Çevrimiçi deneyin!

Arnauld sayesinde -1 bayt

Girişi dize olarak alır. Program oldukça hızlı bir şekilde Python'un özyineleme derinliği sınırına girer, ancak test durumlarının çoğunu bitirebilir.

Nasıl çalışır

l=lambda n,                              # The input number, in the form of a string
         a=0,                            # The program will attempt to reconstruct n by
                                         #  building a string by pasting decreasing
                                         #  numbers, stored in a, after each other.
         c=0,                            # A counter of the amount of numbers
         s="":                           # The current constructed string
              c*(n==s)                   # Return the counter if s matches n
              or                         # Else
              a and l(n,a-1,c+1,s+`a-1`) # If a is not yet zero, paste a-1 after s
              or                         # Else
              l(n,a-~c)                  # Start again, from one higher than last time

1
Güzel cevap! a+c+1kısaltılabilir a-~c.
Arnauld

3

05AB1E , 10 bayt

ÝRŒʒJQ}€gà

Son derece yavaş, bu nedenle aşağıdaki TIO yalnızca 750'nin altındaki test senaryolarında çalışır.

Çevrimiçi deneyin .

Açıklama:

Ý           # Create a list in the range [0, (implicit) input]
            #  i.e. 109 → [0,1,2,...,107,108,109]
 R          # Reverse it
            #  i.e. [0,1,2,...,107,108,109] → [109,108,107,...,2,1,0]
  Œ         # Get all possible sublists of this list
            #  i.e. [109,108,107,...,2,1,0]
            #   → [[109],[109,108],[109,108,107],...,[2,1,0],[1],[1,0],[0]]
   ʒ  }     # Filter it by:
    J       #  Where the sublist joined together
            #   i.e. [10,9] → "109"
            #   i.e. [109,108,107] → "109108107"
     Q      #  Are equal to the (implicit) input
            #   i.e. 109 and "109" → 1 (truthy)
            #   i.e. 109 and "109108107" → 0 (falsey)
       g   # After filtering, take the length of each remaining inner list
            #  i.e. [[109],[[10,9]] → [1,2]
         à  # And only leave the maximum length (which is output implicitly)
            #  i.e. [1,2] → 2

2
Kod golf - programınıza 1 bayt eklemesini gitmek n!için n lg nsadece buna değer değildir.
corsiKa

3

Pyth, 16 bayt

lef!.EhM.+vMT./z

Buradan çevrimiçi olarak deneyin veya tüm test senaryolarını burada bir kerede doğrulayın .

lef!.EhM.+vMT./z   Implicit: z=input as string
             ./z   Get all divisions of z into disjoint substrings
  f                Filter the above, as T, keeping those where the following is truthy:
          vMT        Parse each substring as an int
        .+           Get difference between each pair
      hM             Increment each
   !.E               Are all elements 0? { NOT(ANY(...)) }
 e                 Take the last element of the filtered divisions
                     Divisions are generated with fewest substrings first, so last remaining division is also the longest
l                  Length of the above, implicit print

3

Jöle , 11 bayt

ŒṖḌ’Dɗ\ƑƇẈṀ

Bayt için bayt, diğer Jelly çözümü için eşleşme yok, ancak bu kabaca olmalı Ö(n0.3).

Çevrimiçi deneyin!

Nasıl çalışır

ŒṖḌ’Dɗ\ƑƇẈṀ  Main link. Argument: n (integer)

ŒṖ           Yield all partitions of n's digit list in base 10.
        Ƈ    Comb; keep only partitions for which the link to the left returns 1.
       Ƒ       Fixed; yield 1 if calling the link to the left returns its argument.
      \          Cumulatively reduce the partition by the link to the left.
     ɗ             Combine the three links to the left into a dyadic chain.
  Ḍ                  Undecimal; convert a digit list into an integer.
   ’                 Decrement the result.
    D                Decimal; convert the integer back to a digit list.

3

Kömür , 26 bayt

F⊕LθF⊕Lθ⊞υ⭆κ⁻I…θιλI﹪⌕υθ⊕Lθ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı versiyonudur. Açıklama:

F⊕Lθ

döngü i0'dan giriş uzunluğuna .

F⊕Lθ

döngü k0'dan giriş uzunluğuna .

⊞υ⭆κ⁻I…θ⊕ιλ

İlk ksırada verilen sayıdan başlayarak azalan sırada ilk sayıları hesaplayıni basamakları , birleştirin ve önceden tanımlanmış boş listede her bir sonuç dizesini biriktirin.

I﹪⌕υθ⊕Lθ

Girişin ilk eşleşen kopyasının konumunu bulun ve girişin uzunluğundan daha fazla modulo 1 azaltın.

Örnek: 2019Aşağıdaki dizelerin girişi için:

 0
 1  0
 2  0-1
 3  0-1-2
 4  0-1-2-3
 5  
 6  2
 7  21
 8  210
 9  210-1
10  
11  20
12  2019
13  201918
14  20191817
15  
16  201
17  201200
18  201200199
19  201200199198
20  
21  2019
22  20192018
23  201920182017
24  2019201820172016

2019 daha sonra, istenen cevabı 2 vermek üzere indirgenmiş modulo 5 olan indeks 12'de bulunur.


3

Haskell, 87 bayt

maximum.map length.(0#)
a#(b:c)=[a:x|c==[]||b>0,x<-b#c,a==x!!0+1]++(10*a+b)#c
a#b=[[a]]

Girdi, rakamların listesidir.

Çevrimiçi deneyin!

fonksiyon # , her ikisine de bakarak olası tüm bölünmelerin bir listesini oluşturur

  • geçerli numarayı a, girişin geri kalanıyla ( x<-b#c) yinelemeli bir çağrı tarafından döndürülen tüm bölünmelere ekler , ancak yalnızca sonraki sayı sıfır değilse ( b>0) (veya girişteki son sayıdır ( c==[])) ve abirinciden büyükse önceki bölmenin numarası x( a==x!!0+1).

ve

  • bir sonraki basamağı bgiriş listesinden geçerli sayıya ekleme ve girişin ageri kalanıyla devam etme ( (10*a+b)#c)

Temel durum, giriş listesinin boş olduğu zamandır (yani desen eşleşmiyor (b:c)). Mevcut sayısı ile tekrarlama başlar avarlık 0( (0#)asla ilk şubesini (prepending vurur), abu bölünme herhangi sayısından büyük asla çünkü, önceki tüm bölümlerinize).

Her bölümün uzunluğunu alın ve maksimumu ( maximum.map length) bulun .

Ayrıca 87 baytlık bir varyant:

fst.maximum.(0#)
a#(b:c)=[(r+1,a)|c==[]||b>0,(r,x)<-b#c,a==x+1]++(10*a+b)#c
a#b=[(1,a)]

temelde aynı şekilde çalışır, ancak tüm bölünmeyi bir listede tutmak yerine, bölünmenin (r,x)uzunluğunun yalnızca bir çiftini ve bölünmedeki rilk sayıyı tutar x.


3

Python 3 , 302 282 271 bayt

@ElPedro'nun bahşişi sayesinde -10 bayt.

Girişi dize olarak alır. Temel olarak, sayının daha büyük dilimlerini soldan alır ve sayının bu dilimi için tüm sayılar kullanılarak bir dizi oluşturulabileceğini görür.

R=range
I=int
L=len
def g(n,m,t=1):
 for i in R(1,L(m)+1):
  if I(m)==I(n[:i])+1:
   if i==L(n):return-~t
   return g(n[i:],n[:i],t+1)
 return 1
def f(n):
 for i in R(L(n)):
  x=n[:i]
  for j in R(1,L(x)+1):
   if (I(x)==I(n[i:i+j])+1)*I(n[i]):return g(n[i:],x)
 return 1

Çevrimiçi deneyin!


1
range3 kez kullandığınız R=rangeiçin her iki işlevin dışında tanımlayabilir ve sonra 4 bayt kaydetmek R(whatever)yerine kullanabilirsiniz range(whatever).
ElPedro

3

Japt , 27 bayt

ò pÊÔpÊqÊfl²i1Uì q"l?"¹ÌèÊÉ

Çevrimiçi deneyin! veya Çoğu test durumunu kontrol edin

Bu iyi bir skor değil, ama benzersiz bir yöntem kullanıyor ve çok daha fazla golf için yer olabilir. Ayrıca, 201200199198zaman aşımından kaçınmak dışındaki tüm test durumlarının yeterince iyi çalışmasını sağlar .

Açıklama:

ò                              #Get the range [0...input]
  pÊ                           #Add an "l" to the end
    Ô                          #Reverse it
     pÊ                        #Add an "l" to the end
       qÊ                      #Add an "l" between each number and turn to a string
         f            ¹        #Find the substrings that match this regex:
          l²                   # The string "ll"
            i1                 # With this inserted between the "l"s:
              Uì               #  All the digits of the input
                 q"l?"         #  With optional spaces between each one
                       Ì       #Get the last match
                        èÊ     #Count the number of "l"s
                          É    #Subtract 1

Bence bu 27'e için çalışır
Shaggy


@Shaggy, her ikisi de girişte başarısız oluyor 21201çünkü sıra sonunun doğru hizalanmasını zorlamıyorlar (orijinal sürümümden "virgülle bitiyor" satırı). Bu ya da bu alternatif işe yarıyor.
Kamil Drakari

Ah tamam. Bu durumda: 26 bayt
Shaggy

@Shaggy That ve 28 baytlık çözümler başarısız oldu 210çünkü 0'dan sonra bir sınırlayıcı yok. İşte işe yarayan sabit bir 28 bayt.
Kamil Drakari

2

Haskell, 65 bayt

f i=[y|x<-[0..],y<-[1..length i],i==(show=<<[x+y-1,x+y-2..x])]!!0

Girdi bir dizedir.

Çevrimiçi deneyin!

Tamamen farklı Diğer cevabımdan . Tüm ardışık azalan sayı listelerini giriş listesine eşit olanı bulana kadar çalıştıran basit bir kaba kuvvet.

Giriş numarasını 64 bit tamsayılarla sınırlarsak, döngü yyaparak 6 bayt kaydedebiliriz.[1..19] , çünkü en büyük 64 bit tam sayı 19 basamağa sahiptir ve daha fazla öğeyle listeleri test etmeye gerek yoktur.

Haskell, 59 bayt

f i=[y|x<-[0..],y<-[1..19],i==(show=<<[x+y-1,x+y-2..x])]!!0

Çevrimiçi deneyin!



2

Dyalog APL, 138 bayt

Biraz ağız dolusu, ama büyük sayılar için de hızlı çalışıyor. Eğer varsa çevrimiçi denemek tarafından dfn öneki ⎕←ve rakamlardan oluşan bir liste olarak sağda girdi sağlamak.

{⌈/⍵((≢⊂)×1∧.=2-/10⊥¨⊂)⍨⍤1⊢1,{⍬≡1↓⍵:↑⍬1⋄0=⊃⍵:0,∇1↓⍵⋄↑,0 1∘.,⊂⍤1∇1↓⍵}1↓⍵}

açıklama

İlk olarak, sağdaki dfn , basamak listesini bölümlere ayırmak (ile ) olası yolların bir listesini yinelemeli olarak oluşturur . Örneğin 1 0 1 0 ⊂ 2 0 1 9, iç içe vektörü döndürür (2 0)(1 9).

{
   ⍬≡1↓⍵: ↑⍬1       ⍝ Edge case: If ⍵ is singleton list, return the column matrix (0 1)
   0=⊃⍵: 0,∇1↓⍵     ⍝ If head of ⍵ is 0, return 0 catenated to this dfn called on tail ⍵
   ↑,0 1∘.,⊂⍤1∇1↓⍵  ⍝ Finds 1 cat recursive call on tail ⍵ and 0 cat recursive call on ⍵. 
}                    ⍝ Makes a matrix with a row for each possibility.

Kullanırız 1, başlangıçta 1s sütun eklemek ve ⍵ için geçerli bir bölümler matrisi ile kullanın.

Şimdi sol taraftaki fonksiyon treni parenslerde. Trenin sol argümanı nedeniyle bölümler matrisinin satırı ve sağ argüman kullanıcı girdisidir. Tren en soldaki çatal gibi bir çatal yığını.

((≢⊂)×1∧.=2-/10⊥¨⊂)⍨     ⍝ ⍨ swaps left and right arguments of the train.
                  ⊂       ⍝ Partition ⍵ according to ⍺. 
             10⊥¨         ⍝ Decode each partition (turns strings of digits into numbers)
          2-/             ⍝ Difference between adjacent cells
      1∧.=                ⍝ All equal 1?
   ⊂                      ⍝ Partition ⍵ according to ⍺ again
  ≢                       ⍝ Number of cells (ie number of partitions)
     ×                    ⍝ Multiply.

Bölüm azalan sayılar dizisi oluşturuyorsa, tren dizinin uzunluğunu döndürür. Aksi takdirde sıfır.

⍤1⊢fonksiyon girişini kullanıcı girişi ile bölümler matrisinin her satırı arasına uygular ve matrisin her satırı için bir değer döndürür. 'ın işlenen ve türetilmiş işlevine argüman arasında ayrım yapmak için gereklidir .

⌈/ maksimumu bulur.

Daha kısa bir algoritma bulabilirdim ama aklıma gelen en dolaysız ve en açıklayıcı olan bu yolu denemek istedim.


PPCG'ye Hoşgeldiniz! Bu etkileyici bir ilk gönderi!
Rɪᴋᴇʀ

1

TSQL, 169 bayt

Not: Bu yalnızca giriş bir tamsayıya dönüştürülebildiğinde yürütülebilir.

Döngü için kullanılan özyinelemeli sql.

golfed:

DECLARE @ varchar(max) = '1211109876';

WITH C as(SELECT left(@,row_number()over(order by 1/0))+0t,@+null z,0i
FROM spt_values UNION ALL
SELECT t-1,concat(z,t),i+1FROM C WHERE i<9)SELECT
max(i)FROM C WHERE z=@

Ungolfed:

DECLARE @ varchar(max) = '1211109876';

WITH C as
(
  SELECT
    left(@,row_number()over(order by 1/0))+0t,
    @+null z,
    0i
  FROM
    spt_values
  UNION ALL
  SELECT
    t-1,
    concat(z,t),
    i+1
  FROM C
  WHERE i<9
)
SELECT max(i)
FROM C
WHERE z=@

Denemek


0

R , 101 bayt

function(a,N=nchar(a)){for(x in 1:N)F=max(F,which(Reduce(paste0,seq(substr(a,1,x),,-1,N),a=T)==a));F}

Çevrimiçi deneyin!

Herhangi bir R cevabı olmadan 2 haftadan fazla geçti, bu yüzden kendi mesajımı göndermeye karar verdim :)

Kod "hızlı" kaba kuvvet yaklaşımı kullandığından oldukça hızlı

Kaydedilmemiş kod ve açıklama:

function(a){                  # get string a as input (e.g. "2019")

  N = nchar(a)                # set N = length of a (e.g. 4)
  Y = 0                       # initialize Y = 0 (in the actual code we abuse F)

  for(x in 1:N){              # for x in 1 ... N    

    S = substr(a,1,x)         # get the first x characters of a (e.g. "20" for x=2)

    Q = seq(S,,-1,N)          # create a decreasing sequence (step = -1) 
                              # of length N starting from S converted into integer
                              # (e.g. Q = c(20,19,18,17) for x=2)

    R = Reduce(paste0,Q,a=T)  # concatenate all the increasing sub-sequences of Q
                              # (e.g. R = c("20","2019","201918","20191817") for x=2)

    I = which(R == a)         # Get the index where R == a, if none return empty vector
                              # (e.g. I = 2 for x=2)

    Y = max(Y,I)              # store the maximum index found into Y
  }
  return(Y)                   # return Y
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.