Altın zinciri kes


32

Bir gezgin , şehir dışında bir otelde n gün kalmak zorundadır . Nakit dışında ve kredi kartının kullanım süresi dolmuş. Ama n bağlantılı altın bir zinciri var .

Bu oteldeki kural, sakinlerin her sabah kiralarını ödemeleri gerektiğidir. Gezgin, her gün için altın zincirin bir linkini ödemek için müdürle bir anlaşmaya varıyor. Ancak yönetici, her gün ödeme yaparken yolcunun zincire en az zararı vermesini talep eder. Başka bir deyişle, mümkün olduğu kadar az bağlantıyı kesmek için bir çözüm bulmak zorunda.

Bir bağlantının kesilmesi üç alt zincir oluşturur: biri yalnızca kesilen bağlantıyı ve diğeri her birini içerir. Örneğin, 8 uzunluğundaki bir zincirin üçüncü bağlantısını kesmek, uzunluğun alt zincirlerini oluşturur [2, 1, 5]. Yönetici değişiklik yapmaktan mutluluk duyuyor, bu nedenle gezgin ilk gün uzunluğu 1 olan zincir ile, ardından ikinci gün uzunluğu 2 olan zincirle geri ödeyebiliyor.

Kodunuz n uzunluğunu girmeli ve minimum uzunluktaki kesmek için bir bağlantı listesi vermelidir .

Kurallar :

  • n ,> 0 olan bir tam sayıdır.
  • Bağlantılar için 0 veya 1 tabanlı dizinlemeyi kullanabilirsiniz.
  • Bazı numaralar için çözüm benzersiz değil. Örneğin, n = 15her ikisi de [3, 8]ve [4, 8]geçerli çıktılarsa.
  • Listeyi döndürebilir veya herhangi bir makul ayırıcı ile yazdırabilirsiniz.
  • Bu , yani bayt cinsinden en kısa kod kazanır.

Test durumları :

Input          Output (1-indexed)
1              []
3              [1]
7              [3]
15             [3, 8]
149            [6, 17, 38, 79]

Detaylı örnek

İçin n bağlantıları 3 ve uzunluk subchains 8 sonuçlar kesme = 15, [2, 1, 4, 1, 7]. Bu geçerli bir çözüm çünkü:

 1 = 1
 2 = 2
 3 = 1+2
 4 = 4
 5 = 1+4
 6 = 2+4
 7 = 7
 8 = 1+7
 9 = 2+7
10 = 1+2+7
11 = 4+7
12 = 1+4+7
13 = 2+4+7
14 = 1+2+4+7
15 = 1+1+2+4+7

Sadece bir kesim ile hiçbir çözüm yoktur, bu yüzden bu en uygun çözümdür.

ek

Bu sorunun tamsayı bölümleme ile ilgili olduğunu unutmayın. Biz bir bölme aradığınız P ait n böyle 1'den tüm tamsayılar olduğu n bir alt kümesidir en az bir patition sahip P .

İşte bu sorun için olası bir algoritma hakkında bir YouTube videosu .


"Değişiklik yapma" referansını anlamıyorum. Yayınladığınız örnekte, ikinci günde 2 link zinciri ile ödeme yaparsınız (ve açıklamanıza göre değişiklik olarak 1 link zincirini (önceki gün ile ödediğiniz) geri alın. Ama üçüncü günde, sen öde 1+2. İkinci 2-link zinciri nereden geldi?
Flater

4
@Flater Yöneticide zaten var. Sadece bir tane ödedik. Aslında, RHS yöneticisinin her gün sahip olduğu bağlantılardır
polfosol ఠ_ఠ

Yanıtlar:


15

05AB1E , 23 11 8 bayt

ΔÍN-;иg=

Çevrimiçi deneyin!

0 tabanlı endeksleme kullanır.

Açıklama:

             # start from the implicit input
Δ            # loop forever
 Í           # subtract 2
  N-         # subtract the current iteration number
    ;        # divide by 2
     и       # create a list of length x
      g      # get the length of the list
       =     # print

иgnoop'a benziyor, ancak aslında iki yararlı şey yapıyor: bir tamsayıya kısılıyor ( ;bir kayan noktaya döner) ve x negatifse tercümanı çökertiyor (bu sadece çıkış koşulu budur).


23 baytlık çözüm çok farklı bir yaklaşım kullandı, bu yüzden işte adaylık için: ÅœʒR2äθP}ʒæOê¥P}θ2äθη€O( TIO , açıklama ).


2
Cevabımı sildim. Benimki 42 ve seninki 11 olmak, kendimi utandırmamak için çok büyük bir fark, haha. ;) Güzel cevap olsa da, ve lol Ø.Ø. Negatifleri hem yere döşemek hem de haritalandırmak için rastgele bazı şeyler denediniz -1mi? Ne olursa olsun, çok güzel bir cevap ve beklediğimden çok daha kısa. Kötü 42 byte'ımı gönderdikten sonra yaklaşık 20 byte düşünüyordum.
Kevin Cruijssen

2
@KevinCruijssen Nnope, Ø.Øaslında benim ilk fikrimdi. Yorumunuz rastgele şeyler denemek için bana ilham: buldum ®Ÿà, ï®Mve daha da önemlisi, иgbu güzel 8-Byter verir ki. Her zaman osabie'nin birçok durumda çarpma konusunda hiçbir şey yapmamayı tercih ettiğini (0'a göre div, yanlış tip vb.) Rahatsız edici buldum, bu yüzden bu çarpışma işe yarayacak.
Grimmy

2
Hehe, 05AB1E'nin asla çökmemesi gerekiyordu, ama haklısın bazen canını sıkması biraz can sıkıcıdır. sıfır hata el ile arayabiliriz. xD Yeni sürümde, belirli yapılara yanlış argümanlar verirken oldukça sık bir hatayla çarpışıyor. Ve yine güzel -3.
Kevin Cruijssen

2
"eğer x negatifse tercümanı çökertir (bu sadece çıkış şartıdır)." - Bunu seviyorum
John Dvorak

9

Python 2,75 bayt

f=lambda n,i=0:n>=i<<i and f(n,i+1)or[min(n,2**j*i-i+j)for j in range(1,i)]

Çevrimiçi deneyin!


Açıklama:

Kesim sayısına uygun bir taban numarasına sahip bir 'ikili' topakları dizisi oluşturur.

Örneğin:

63 3 ayrı kesimde yapılabilir, bu, taban 4'te bir bölüm anlamına gelir (3 tek halkamız olduğu gibi):

Keser: 5, 14, 31, zincirlerini verir 4 1 8 1 16 1 32(kriteri: 1 1 1 4 8 16 32).

Tüm numaralar yapılabilir:

1       1
2       1 1
3       1 1 1
4       4
...
42      1 1 8 32
...
62      1 1 4 8 16 32
63      1 1 1 4 8 16 32

Diğer örnekler:

18: 4,11        ->  3 1 6 1 7
27: 5,14,27     ->  4 1 8 1 13 1
36: 5,14,31     ->  4 1 8 1 16 1 5
86: 6,17,38,79  ->  5 1 10 1 20 1 40 1 7

1
Başına eklememeli miydin f=? fLambda işlevinde bir çağrı kullandığınızdan ve yalnızca tanımladığınız lambdaya başvurduğunuzu varsayabiliyorum.
randomdude999

@ randomdude999, Evet, unuttum ...
TFeld

@ randomdude999 bu kural tüm dillere mi, yoksa sadece python'a mı uygulanıyor? Çünkü bu mücadelede saf bir lambda olan bir javascript cevabı görüyorum ...
Shadow

3
@Shadow Tüm diller için geçerlidir, ancak sadece özyinelemeli lambdalar için geçerlidir.
TFeld

1
@Shadow Daha genel bir kural, zorlukla açıkça izin verilmediği sürece, kodunuzda tanımlanmayan veya dilinizde genel olarak tanımlanmış bir şeye başvuru yapamamanızdır. En sık karşılaşılan durum özyinelemeli bir işlevdir, ancak bu diğer durumlar için de geçerlidir. Bu cevap başka bir örnektir: fözyinelemeli değildir, ancak kodda referans verilmiştir ve bu nedenle adlandırılmaları gerekir.
Arnauld

8

R , 77 69 bayt

Aaron Hayman sayesinde -8 bayt

pmin(n<-scan(),0:(k=sum((a=2:n)*2^a<=n))+cumsum((k+2)*2^(0:k))+1)[-n]

Çevrimiçi deneyin!

kk(k+1)2kn1,1,...,1k(k+1),2(k+1),4(k+1),8(k+1),...,(k+1)2k-1

(Zincirin toplam uzunluğunu aşarsak, son alt zincirin daha kısa yapılması gerekebilir.)

Ungolfed (önceki, benzer sürümlere göre):

n = scan()                            # read input
if(n - 1){                            # If n==1, return NULL
  k = match(F, (a = 2:n) * 2 ^ a > n) # compute k
  b = (k + 1) * 2 ^ (1:k - 1)         # lengths of subchains
  c = 1:k + cumsum(b)                 # positions of cuts
  pmin(c, n )                         # if last value is >n, coerce it to n
}

kkkk+12k+12k+24k+4k(k+1)2k-1.)

bir(k)nkbir(k)


Bunun için özel durum için yardımcı olacağından şüpheliyim n=1, ancak kesimleri oluşturmanın alternatif bir yolu da tekrarlamadır 1, 4, 4a(n-1)-4a(n-2).
Peter Taylor,

@ PeterTaylor Hesaplama için benzer bir yineleme yaşadım k; bu, OEIS A134401'e tekabül eder: oeis.org/A134401 Ancak yineleme ilişkisini uygulamam mevcut koddan daha fazla bayt alır.
Robin Ryder

Biraz yeniden düzenleme 73'e düştüm . Çevrimiçi deneyin!
Aaron Hayman

@AaronHayman Teşekkürler! Akıllı hareket sumyerine kullanma match.
Robin Ryder

69 bayt ve sizi üzen ifadeden kurtuldum: Çevrimiçi deneyin!
Aaron Hayman



2

C ++, 109 , 107 bayt

Kevin sayesinde -2 bayt

#include<iostream>
main(){int n,k=0;for(std::cin>>n;++k<<k<n;);for(n-=k;n>0;k*=2,n-=k+1)std::cout<<n<<',';}

Algoritma Robin Ryder'ın cevabına benzer. Kod derlenebilir, tam bir biçimde yazılmıştır. Dene!

Detaylar:

std::cin>>n;               // get the value of n as input
while(++k<<k<n);           // determine k
for(n-=k;n>0;k*=2,n-=k+1)  // we don't need n, so the lengths...
    std::cout<<n<<' ';     // of links are subtracted repeatedly

Bu, aynı bayt uzunluğunda bir C varyasyonuna sahiptir (ayrı bir cevaba ihtiyaç duymaz):

#include<stdio.h>
main(){int n,k=0;for(scanf("%d",&n);++k<<k<n;);for(n-=k;n>0;k*=2,n-=k+1)printf("%d,",n);}

Golf için iki küçük şeyler: =0 sonra varsayılan olarak k, çünkü kaldırılabilir 0. std::cin>>n;while(++k<<k<n);olabilir for(std::cin>>n;++k<<k<n;);. Ayrıca bazı for(n-=k;n>0;k*=2,n-=k+1)şeyleri birleştirerek bir şekilde sadeleştirilebileceğini de hissediyorum , ama nasıl olduğundan emin değilim. PS: Virgül sınırlayıcıyı bir boşluğa değiştirmek, takip eden bir
imoyu

1
@KevinCruijssen Teşekkürler, ancak bazı derleyiciler statik olmayan değişkenlere varsayılan bir değer atamaz. Bu yüzden =0taşınabilirlik için gerekli olduğunu düşündüm ;) Ayrıca boşluğun #includegerekli olmadığını da fark ettim .
polfosol ఠ_ఠ

Ah tamam. C ++ 'ı çok iyi tanımıyorum, bu yüzden cevabınıza bağladığınız çevrimiçi derleyiciyi bazı şeyleri test etmek için kullandım. :) Benim yorumumda önerdiğim ikinci değişikliği unuttun: while döngüsü için for döngüsü ve içine koyarak std::cin>>n.
Kevin Cruijssen


1

Retina 0.8.2 , 61 bayt

.+
11,$&$*
+`\b(1+),(\1(1*)1?\3)$
1$2¶1$1,$3
1+,
1
1A`
1+
$.&

Çevrimiçi deneyin! Grimy'nin cevabının 1 indeksli limanı. Açıklama:

.+
11,$&$*

İle başlayın N=2ve giriş birliğe dönüştürülür.

+`\b(1+),(\1(1*)1?\3)$

Arka arkaya Ngirişten çıkarmaya çalışın ve sonra 2'ye bölün.

1$2¶1$1,$3

Başarılı olursa, önceki satırdaki girişden 1 tanesini hatırlayın N, geçerli satırdaki artışı artırın ve girişi yeni değerle güncelleyin.

1+,
1

NSon değeri kaldırın ve arttırın, böylece 1 indekslenmiş olur.

1A`

Arttırılmış orijinal girişi çıkarın.

1+
$.&

Sonuçları ondalık basamağa dönüştürün.


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.