A, Ctrl + A, Ctrl + C ve Ctrl + V tuş vuruşlarını kullanan maksimum karakter sayısı


106

Bu, google'dan bir röportaj sorusu. Tek başıma çözemiyorum. Biri biraz ışık tutabilir mi?

Maksimum 'A karakterini oluşturacak şekilde tuş vuruşlarının sırasını yazdırmak için bir program yazın. Yalnızca 4 tuşlarını kullanmak izin verilir: A, Ctrl+ A, Ctrl+ Cve Ctrl+ V. Yalnızca N tuş vuruşuna izin verilir. Tüm Ctrl+ karakterler tek bir tuş vuruşu olarak kabul edilir, bu nedenle Ctrl+ Abir tuş vuruşudur.

Örneğin A, Ctrl+ A, Ctrl+ C, Ctrl+ dizisi V4 tuş vuruşunda iki A üretir.

  • Ctrl + A Tümünü Seçtir
  • Ctrl + C Kopyaladır
  • Ctrl + V Yapıştır

Biraz matematik yaptım. Herhangi bir N için, x A sayısı, bir Ctrl+ A, bir Ctrl+ Cve y Ctrl+ Vkullanarak, maks ((N-1) / 2) 2 A sayısı üretebiliriz . Bazı N> M için, A'ların sayısını iki katına çıkardığı için çok sayıda Ctrl+ A's, Ctrl+ Cve Ctrl+ Vdizisi kullanmak daha iyidir .

Ctrl+ A, Ctrl+ V, Ctrl+ Dizisi Cmevcut seçimin üzerine yazmayacaktır. Kopyalanan seçimi seçilene ekleyecektir.


Birçok metin düzenleyicide ^Agenellikle "tümünü seç", ^C"kopyala", ^V"yapıştır" dır. Bu sana bir fikir veriyor mu?
Nikolai Fetissov

"A" sayısı demek istiyorum. Örneğin, N = 7 için 9 A'yı A, A, A, CTRL + A, CTRL + C, CTRL + V, CTRL + V
munda

Uh, bu 7 tuş vuruşu.
John Dibling

@John "Tüm CTRL + karakterleri tek bir tuş vuruşu olarak kabul edilir, bu nedenle CTRL + A bir tuş vuruşudur."
fredley

1
C ++ etiketini kaldırdım, bu tamamen bir algoritma sorusudur ve umarım mutsuz c ++ takipçilerinin kapatma için olumsuz oy kullanmasını / oy kullanmasını engeller.
Matthieu M.

Yanıtlar:


43

Dinamik bir programlama çözümü var. 0 tuşunun bizi 0 A yapabileceğini bilerek başlıyoruz. Sonra için aracılığıyla biz yinelerler iiçin yukarı n, iki şey yapıyor: Bir kez A tuşlarına basarak ve tüm seçmek için, + basarak macun ardından kopya jaslında (bazen j-i-1aşağıda; notu burada hüner: Biz olmadan bunu birden çok kez yapıştırın böylece içeriği panoya hala her seferinde kopyalama). Seç, kopyala, yapıştır x 5 seçmek, kopyalamak, yapıştırmak, seçmek, kopyalamak, yapıştırmakla eşdeğer olduğu ve ikincisi panoda bize daha fazlasını bıraktığı için daha iyi olduğu için yalnızca 4 ardışık yapıştırmayı dikkate almalıyız. Bir kez ulaştığımızda n, istenen sonucu elde ederiz.

Karmaşıklık O (N) gibi görünebilir, ancak sayılar üstel bir oranda büyüdüğünden , büyük sayıları çarpmanın karmaşıklığından dolayı aslında O (N 2 ) 'dir. Aşağıda bir Python uygulaması bulunmaktadır. N = 50.000 için hesaplamak yaklaşık 0,5 saniye sürer.

def max_chars(n):
  dp = [0] * (n+1)
  for i in xrange(n):
    dp[i+1] = max(dp[i+1], dp[i]+1) # press a
    for j in xrange(i+3, min(i+7, n+1)):
      dp[j] = max(dp[j], dp[i]*(j-i-1)) # press select all, copy, paste x (j-i-1)
  return dp[n]

Kodunda, jtuş basımlarının yeni dizisinden sonra preslenmiş anahtarların sayısını ifade eder. iBu aşamada zaten tuşlara basma işlemimiz var ve 2 yeni tuşa basışımız tümünü seç ve kopyala seçeneğine gidiyor. Bu nedenle yapıştırma j-i-2sürelerine ulaşıyoruz . Yapıştırma, var olan dp[i] A'lar dizisini eklediğinden 1, onu yapmaya eklememiz gerekir j-i-1. Bu j-i-1, 2.-son satırdaki açıklıyor .

İşte bazı sonuçlar ( n=> A sayısı):

  • 7 => 9
  • 8 => 12
  • 9 => 16
  • 10 => 20
  • 100 => 1391569403904
  • 1,000 => 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245 174442911064952028008546304
  • 50.000 => çok büyük bir sayı!

Her zaman varsayımlarınızı belirtmeniz gerektiği konusunda @SB'ye katılıyorum: Benimki, karakter sayısını ikiye katlamak için iki kez yapıştırmanıza gerek olmadığıdır. Bu 7'nin cevabını alıyor, bu yüzden benim çözümüm yanlış olmadığı sürece varsayım doğru olmalı.

Ben formun dizileri kontrol değilim neden vaka birisi harikalar olarak Ctrl+ A, Ctrl+ C, A, Ctrl+ V: Sonuç hep aynı olacaktır A, Ctrl+ A, Ctrl+ C, Ctrl+ Vben hangi do düşünün.


Bu mu n => resultyoksa result => n? Her iki durumda da yanlış olduğunu düşünüyorum. 7 tuşa basarak 9 As yazabiliriz. Eğer n => resultkesinlikle yanlışsa. Yazabileceğiniz As sayısı şundan küçük olamaz n.
IVlad

@Vlad It's n => result. "7 tuş vuruşuyla 9 gibi yazabiliriz" diyorsunuz, ki bunu elde ederim. Yeni düzenlediğim "numara"

Bu harika görünüyor, ancak sorunun belirli sayıda A elde etmek için gereken minimum tuş vuruşu sayısını değil, belirli bir tuş vuruşu sayısı için maksimum A sayısını bulmak olması dışında.
Andrew Clark

1
@marcog - gösteriminiz en azından kafa karıştırıcı ve en çok yanlış. nkullanmanıza izin verilen tuş vuruşlarıdır. nTuş vuruşlarıyla kaç tane yazabileceğinizi hesaplamalısınız . Yani 7 => 7hiç mantıklı değil.
IVlad

1
Doğru görünüyor, + 1. Şimdi bakalım birisi bunu indirebilir mi, O(n)hatta O(1):).
IVlad

41

Marcog'un çözümünü kullanarak, ile başlayan bir model buldum n=16. Bunu açıklamak n=24için n=29, ^ A'yı S (seç) ile, ^ C'yi C (kopyala) ile ve ^ V'yi P (yapıştır) ile değiştirdim okunabilirlik için tuş vuruşları :

24: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4     = 1024
25: A,A,A,A,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *   3   *   3   *   3   *   3    = 1296
26: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *   3   *   3   *   3    = 1728
27: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *    4    *   3   *   3    = 2304
28: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P
       4   *    4    *    4    *    4    *    4    *   3    = 3072
29: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4    *    4     = 4096

İlk 4 As'dan sonra ideal model seçmek, kopyalamak, yapıştırmak, yapıştırmak, yapıştırmak ve tekrar etmektir. Bu, As sayısını her 5 tuş vuruşunda bir 4 ile çarpacaktır. Bu 5 tuş vuruşu modeli, kalan tuş vuruşlarını kendi başına tüketemezse, bazı 4 tuş vuruşu kalıbı (SCPP), SCPPP'yi değiştirerek (veya yapıştırmalardan birini kaldırarak) son tuş vuruşlarını tüketir. 4 tuş vuruşu paterni, toplamı her 4 tuş vuruşunda 3 ile çarpar.

Bu kalıbı burada kullanmak, marcog'un çözümüyle aynı sonuçları alan, ancak O (1) düzenlemesi olan bazı Python kodudur : Bu aslında üs alma nedeniyle O (log n), bunu işaret ettiği için IVlad sayesinde.

def max_chars(n):
  if n <= 15:
    return (0, 1, 2, 3, 4, 5, 6, 9, 12, 16, 20, 27, 36, 48, 64, 81)[n]
  e3 = (4 - n) % 5
  e4 = n // 5 - e3
  return 4 * (4 ** e4) * (3 ** e3)

E3'ün hesaplanması: Tuş vuruşu listesinin sonunda her zaman 0 ile 4 arasında SCPP örüntüsü n % 5 == 4vardır, n % 5 == 1çünkü 4 vardır, 3 n % 5 == 2vardır, 2 n % 5 == 3vardır, 1 n % 5 == 4vardır ve 0 vardır. Bu basitleştirilebilir (4 - n) % 5.

E4'ün hesaplanması: Toplam desen sayısı 1 artar n % 5 == 0, çünkü bu sayı tam olarak artar n / 5. Kat bölmesini kullanarak toplam desen sayısını elde edebiliriz, toplam desen e4sayısı eksi toplam desen sayısıdır e3. Python'a aşina olmayanlar //için, zemin bölümü için geleceğe dönük notasyondur.


1
Güzel bir! Test edildi ve işe yarıyor n=3000, bu yüzden muhtemelen doğru. (Yazık bugün oy
kaybım

5
+1, çok güzel. Yine de küçük nitpick: O(1)sabit zamanda üs alma yapılamayacağı için gerçekten değil. Bu O(log n).
IVlad

2
Aslında, 'SCPPP' dizisi karakter sayısını yalnızca üçe çarpacaktır: ilk yapıştırma, seçili metnin üzerine yazar.
Nick Johnson

4
@Nick Sorudaki son satır: "Ctrl + A, Ctrl + V, Ctrl + C dizisi mevcut seçimin üzerine yazmaz. Kopyalanan seçimi seçilene ekler."
moinudin

2
@marcog Evet, bunu fark etmedim. Yine de bu şekilde davranan herhangi bir işletim sistemi bilmiyorum.
Nick Johnson

15

İşte ona nasıl yaklaşacağım:

  • varsaymak CtrlA= tümünü seç
  • varsaymak CtrlC= seçimi kopyala
  • assume CtrlV= kopyalanan seçimi yapıştır

bir metin verildiğinde, kopyalamak için 4 tuş vuruşu gerekir:

  • CtrlA hepsini seçmek
  • CtrlC kopyalamak için
  • CtrlV yapıştırmak için (bu seçimin üzerine yapıştırılır - VARSAYIMLARINIZI BİLDİRİN)
  • CtrlV tekrar yapıştırın, bu da onu ikiye katlar.

Oradan 4 veya 5 A yapmayı ve ardından yukarıdakileri tekrarlamayı düşünebilirsiniz. Yapıyor bu Not ctrl + a, c, v, varacılığıyla size döngü gibi katlanarak metni büyüyecektir. Kalan vuruşlar <4 ise,CtrlV

Google gibi yerlerde röportaj yapmanın anahtarı, varsayımlarınızı belirtmek ve düşüncelerinizi iletmektir. problemleri nasıl çözdüğünüzü bilmek isterler.


6
Görüşme tekniği hakkında iyi bir nokta, doğru cevabı almak, sonunda net bir şekilde iletişim kurmaktan daha az önemlidir!
fredley

2
İyi cevap. Algoritma için açgözlü bir ikiye ACVV-VVVVVACVV-ACVV-V
bölünmüş

5

O (1) 'de çözülebilir: Fibonacci sayılarında olduğu gibi, yazdırılan As sayısını (ve tuş vuruşlarının sırasını) hesaplamak için bir formül vardır:


1) Sorun açıklamasını basitleştirebiliriz:

  • Yalnızca [A], [Ca] + [Cc], [Cv] ve boş bir kopyala-yapıştır arabelleğine sahip olmak

eşittir

  • kopyala-yapıştır tamponunda sadece [Ca] + [Cc], [Cv] ve "A" bulunan.

2) Tuş vuruşlarının sırasını {'*', 'V', 'v'} 'den oluşan N karakter dizisi olarak tanımlayabiliriz, burada' v '[Cv] ve' * '[Ca] ve' V anlamına gelir '[Cc] anlamına gelir. Örnek: "vvvv * Vvvvv * Vvvv"

Bu dizenin uzunluğu hala N'ye eşittir.

Bu dizedeki Vv kelimelerinin uzunluklarının çarpımı, üretilen As sayısına eşittir.


3) Bu dizge için sabit bir uzunluk N ve sabit sayıda K kelimesi verildiğinde, tüm kelimeler neredeyse eşit uzunluklara sahipse sonuç maksimum olacaktır. İkili farkı ± 1'den fazla değil.

Şimdi, eğer N verilirse optimal K sayısı nedir?


4) Farz edelim ki, L uzunluğunda tek bir kelime ekleyerek kelime sayısını artırmak istiyoruz, o zaman L + 1'i önceki herhangi bir kelimeyi bir 'v' ile azaltmak zorundayız. Örnek: "… * Vvvv * Vvvv * Vvvv * Vvvv" -> "… * Vvv * Vvv * Vvv * Vvv * Vvv"

Şimdi, optimal kelime uzunluğu L nedir?

(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3

=> Optimal, L = 4'tür.


5) Diyelim ki, 4 uzunluğunda birçok kelimeden oluşan bir dizge oluşturmak için yeterli büyük bir N'ye sahibiz, ancak birkaç tuş vuruşu kaldı; onları nasıl kullanmalıyız?

  • 5 veya daha fazla sol varsa: 4 uzunluğunda başka bir kelime ekleyin.

  • 0 varsa: Bitti.

  • 4 tane kaldıysa: Biz de yapabiliriz

    a) 3: 4 * 4 * 4 * 4 * 3 = 768 uzunluğunda bir kelime ekleyin.

    b) veya 4 kelimeyi 5: 5 * 5 * 5 * 5 = 625 uzunluğuna yükseltin. => Bir kelime eklemek daha iyidir.

  • 3 tane kaldıysa: Biz de yapabiliriz

    a) veya önceki kelimeyi uzunluk 4'ten 3'e ayarlayarak uzunluğu 3 olan bir kelimeyi ekleyin: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.

    b) 3 kelimeyi 5: 5 * 5 * 5 = 125 uzunluğa çıkarın. => Bir kelime eklemek daha iyidir.

  • 2 tane kaldıysa: Biz de yapabiliriz

    a) veya önceki iki kelimeyi uzunluk 4'ten 3'e ayarlayarak uzunluğu 3 olan bir kelimeyi ekleyin: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.

    b) 2 kelimeyi 5: 5 * 5 = 25 uzunluğuna yükseltin. => Bir kelime eklemek daha iyidir.

  • 1 tane kaldıysa: Biz de yapabiliriz

    a) veya önceki üç kelimeyi uzunluk 4'ten 3'e ayarlayarak 3 uzunluğundaki bir kelimeyi ekleyin: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.

    b) bir kelimeyi 5: 4 * 4 * 5 = 80 uzunluğa çıkarın. => Bir kelime eklemek daha iyidir.


6) Şimdi, 5) 'deki kuralları kullanmak için "yeterli büyük N" ye sahip değilsek ne olur? Mümkünse b) planına bağlı kalmalıyız! Küçük N dizeleri şunlardır:

1: "v", 2: "vv", 3: "vvv", 4: "vvvv"

5: "vvvvv" → 5 (plan b)

6: "vvvvvv" → 6 (plan b)

7: "vvv * Vvv" → 9 (plan a)

8: "vvvv * Vvv" → 12 (plan a)

9: "vvvv * Vvvv" → 16

10: "vvvv * Vvvvv" → 20 (plan b)

11: "vvv * Vvv * Vvv" → 29 (plan a)

12: "vvvv * Vvv * Vvv" → 36 (plan a)

13: "vvvv * Vvvv * Vvv" → 48 (plan a)

14: "vvvv * Vvvv * Vvvv" → 64

15: "vvv * Vvv * Vvv * Vvv" → 81 (plan a)


7) Şimdi, N uzunluğunda bir dizideki en uygun K kelime sayısı nedir?

N <7 ise K = 1, aksi takdirde 6 <N <11 ise K = 2; aksi halde: K = ceil ((N + 1) / 5)

C / C ++ / Java'da yazılmıştır: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);

Ve N> 10 ise, 3 uzunluğundaki kelimelerin sayısı: K * 5-1-N olacaktır. Bununla, yazdırılan sayıyı şu şekilde hesaplayabiliriz:

N> 10 ise, As sayısı: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1} olacaktır


Doğru gibi görünüyor, @ Andrew'un cevabında verilen örnekler için çalışıyor, ancak cevabınız da O (1) yerine O (log N), değil mi?
rsenna

Nasıl O olabilir (log N)? As sayısını hesaplamak için kullanılan matematiksel formül O (1) 'de hesaplanır. Tuş vuruşlarını yazdırma algoritması, yazdırılacak O (N) tuş vuruşları olduğu için O (N) veya normal ifade olarak yazdırmanıza izin verirseniz O (1) şeklindedir.
komonad

Üstün hesaplanması O (log N) 'dir, çünkü 4 üzerindeki üs N ile artar. As sayısını çarpanlara ayrılmış biçimde yazdırırsanız, O (1) olur.
Andrew Clark

Ah tamam. Tam sayı aritmetiği ile sayıyı gerçekten hesaplamayı hiç düşünmedim. Sadece formülle veya kayan nokta tahminiyle ilgilenirim. Ama elbette, onu diğer sayılarla karşılaştırabilmek için, tam olarak hesaplanması gerekirdi.
comonad

5

CtrlA+ CtrlC+ Kullanmak CtrlVancak 4 'A'dan sonra bir avantajdır.

Bu yüzden şöyle bir şey yapardım (sözde BASIC kodunda, çünkü herhangi bir uygun dil belirlemediniz):

// We should not use the clipboard for the first four A's:
FOR I IN 1 TO MIN(N, 4)
    PRINT 'CLICK A'
NEXT
LET N1 = N - 4

// Generates the maximum number of pastes allowed:
FOR I IN 1 TO (N1 DIV 3) DO
    PRINT 'CTRL-A'
    PRINT 'CTRL-C'
    PRINT 'CTRL-V'
    LET N1 = N1 - 3
NEXT

// If we still have same keystrokes left, let's use them with simple CTRL-Vs
FOR I IN N1 TO N
    PRINT 'CTRL-V'
NEXT

Düzenle

  1. CtrlVAna döngüde bir single kullanmaya geri dönün .
  2. Burada ne yapmaya çalıştığımı açıklamak için bazı yorumlar ekledim.
  3. "İlk dört A" bloğuyla ilgili bir sorun düzeltildi.

@SB: Sadece SON yapıştırmalar için CTRL-V yapıyorum . Bu arada, cevabında tam olarak söylediğin şey bu. Bu da benzer düşündüğümüz anlamına geliyor, bu yüzden beni neden eleştirdiğinizi bilmiyorum - ya da belki bir şeyi kaçırıyorum?
rsenna

1
google asla, hangisini isterseniz, yazmak için uygun bir dil belirtmez.
Spooks

3

A sayınızı ikiye katlamak için 3 tuş vuruşu gerekir. Daha önce yazdırıldığı gibi 3 veya daha fazla eliniz olduğunda ikiye katlamaya başlamak mantıklıdır. İzin verilen son tuş vuruşunuzun, CtrlVyapabileceğiniz en büyük sayıyı ikiye katladığınızdan emin olmak için bir olmasını istiyorsunuz, bu nedenle onu hizalamak için ilk üçten sonraki tüm ekstra tuş vuruşlarını Başta As ile dolduracağız.

for (i = 3 + n%3; i>0 && n>0; n--, i--) {
    print("a");
}

for (; n>0; n = n-3) {
    print("ctrl-a");
    print("ctrl-c");
    print("ctrl-v");
}

Düzenle:

Bu korkunç, tamamen kendimin önüne geçtim ve her kopya için birden fazla macun düşünmedim.

Düzenleme 2:

Bunu yapmak için yeterli tuş vuruşunuz olduğunda 3 kez yapıştırmanın en uygun olduğuna inanıyorum. 5 tuş vuruşunda As sayınızı 4 ile çarparsınız. Bu, 4 tuş vuruşu kullanarak 3 ile çarpmaktan ve 6 tuş vuruşu kullanarak 5 ile çarpmaktan daha iyidir. Bunu, her yönteme aynı sayıda tuş vuruşu vererek karşılaştırdım, yeter ki her biri bir döngüyü aynı anda bitirsin (60), 3 çarpanın 15 döngü yapmasına, 4 çarpanın 12 döngü yapmasına ve 5 çarpan 10 döngü yapar. 3 ^ 15 = 14,348,907, 4 ^ 12 = 16,777,216 ve 5 ^ 10 = 9,765,625. Yalnızca 4 tuş vuruşu kaldıysa, 3 çarpan yapmak, 4 kez daha yapıştırmaktan daha iyidir, esasen önceki 4 çarpanı 8 çarpanı haline getirir. Yalnızca 3 tuş vuruşu kaldıysa, 2 çarpan en iyisidir.


2

Panoda x karakteriniz ve metin alanında x karakteriniz olduğunu varsayalım; buna "durum x" diyelim.

Birkaç kez "Yapıştır" a ( m-1kolaylık olması açısından ile gösteriyorum), ardından "Tümünü seç" ve "Kopyala" yı tıklayalım; bu diziden sonra "m * x durumu" na geçiyoruz. Burada toplam m + 1 tuş vuruşunu boşa harcadık. Yani asimptotik büyüme (en azından) gibi bir şeydir f^n, burada f = m^(1/(m+1)). Bunun mümkün olan maksimum asimptotik büyüme olduğuna inanıyorum, ancak bunu kanıtlayamasam da (henüz).

Çeşitli m değerlerini denemek, f için maksimumun elde edildiğini gösterir m=4.

Aşağıdaki algoritmayı kullanalım:

Press A a few times
Press Select-all
Press Copy
Repeat a few times:
    Press Paste
    Press Paste
    Press Paste
    Press Select-all
    Press Copy
While any keystrokes left:
    Press Paste

(bunun en uygun olduğundan emin değilim).

Başlangıçta A'ya basma sayısı 3'tür: 4 kez basarsanız, 3 tuş vuruşunda daha A sayısını ikiye katlama fırsatını kaçırırsınız.

Sonunda Yapıştır'a basma sayısı 5'ten fazla değildir: 6 veya daha fazla tuş vuruşunuz kaldıysa, bunun yerine Yapıştır, Yapıştır, Yapıştır, Tümünü Seç, Kopyala, Yapıştır seçeneklerini kullanabilirsiniz.

Böylece aşağıdaki algoritmayı elde ederiz:

If (less than 6 keystrokes - special case)
    While (any keystrokes left)
        A
Else
    First 5 keystrokes: A, A, A, Select-all, Copy
    While (more than 5 keystrokes left)
        Paste, Paste, Paste, Select-all, Copy
    While (any keystrokes left)
        Paste

(bunun en uygun olduğundan emin değilim). Bunu yürüttükten sonraki karakter sayısı şuna benzer:

3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5).

Örnek değerler: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...


2

Aşağıda yapıştırma yaptığı OP'ın ikinci düzenlemeyi kullanan değil mevcut metnin yerini .

Birkaç şeye dikkat edin:

  • ^ A ve ^ C, iki tuş vuruşu gerektiren tek bir eylem olarak kabul edilebilir, çünkü bunları tek tek yapmak hiçbir zaman mantıklı değildir. Aslında, tüm ^ A ^ C örneklerini ^ K ^ V ile değiştirebiliriz, burada ^ K tek tuşlu "kesme" işlemidir (X'i kısaltalım). ^ K ile uğraşmanın iki maliyetli ^ A ^ C'den çok daha iyi olduğunu göreceğiz.
  • Panoda bir "A" nın başladığını varsayalım. O halde ^ V (Y'yi kısaltalım) kesinlikle A'dan üstündür ve ikincisini tüm düşüncelerden çıkarabiliriz. (Asıl problemde, pano boş başlarsa, takip eden bölümde, ilk X'e kadar Y'yi ^ V yerine A ile değiştireceğiz.)

Her makul tuş vuruşu dizisi bu nedenle X'ler ile ayrılmış bir Y grubu olarak yorumlanabilir, örneğin YYYXYXYYXY. S dizisi tarafından üretilen 'A'ların sayısını V (s) ile ifade edin. O zaman V (nXm) = V (n) * V (m), çünkü X esasen m'deki her Y'yi V (n) 'A ile değiştirir.

Kopyala-yapıştır problemi bu nedenle aşağıdaki problemle izomorfiktir: "Nm'ye toplamı olan m + 1 sayıları kullanarak onların çarpımını maksimize edin." Örneğin, N = 6 olduğunda cevap m = 1 ve sayılardır (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (veya V (YYYXYY) = V (AAA ^ A ^ C ^ V).)

Birkaç gözlem yapabiliriz:

Bir İçin Sabit değerine mseçmek için, sayı vardır ceil( (N-m)/(m+1) )ve floor( (N-m)/(m+1) )(her ne kombinasyon toplamı çalışma dışarı yapar; daha spesifik ihtiyacınız olacak (N-m) % (m+1) ceilsve geri kalan floorler). Bu için, çünkü a < b, (a+1)*(b-1) >= a*b.

Maalesef değerini bulmanın kolay bir yolunu göremiyorum m. Bu benim röportajım olsaydı, bu noktada iki çözüm önerirdim:

Seçenek 1. Mümkün olan her şeyin üzerinden döngü yapın m. Bir O (n log n ) çözümü.

C ++ kodu:

long long ipow(int a, int b)
{
  long long val=1;
  long long mul=a;

  while(b>0)
    {
      if(b%2)
    val *= mul;
      mul *= mul;
      b/=2;
    }
  return val;
}

long long trym(int N, int m)
{
  int floor = (N-m)/(m+1);
  int ceil = 1+floor;
  int numceils = (N-m)%(m+1);
  return ipow(floor, m+1-numceils) * ipow(ceil, numceils);
}

long long maxAs(int N)
{
  long long maxval=0;
  for(int m=0; m<N; m++)
    {
      maxval = std::max(maxval, trym(N,m));
    }
  return maxval;
}

Seçenek 2. mTamsayı olmayan değerlerin elde [(N-m)/(m+1)]^medilmesine mve köküne göre türevini alarak ve bunun için çözerek optimal değerini bulmaya izin verin . Analitik bir çözüm yoktur, ancak kök, örneğin Newton yöntemi kullanılarak bulunabilir. Daha sonra değeri için bu kökün tabanını ve tavanını kullanın mve hangisinin en iyi olduğunu seçin.


0
public int dp(int n) 
{
    int arr[] = new int[n];
    for (int i = 0; i < n; i++)
        arr[i] = i + 1;
    for (int i = 2; i < n - 3; i++) 
    {
        int numchars = arr[i] * 2;
        int j = i + 3;
        arr[j] = Math.max(arr[j], numchars);
        while (j < n - 1) 
        {
            numchars = numchars + arr[i];
            arr[++j] = Math.max(arr[j], numchars);
        }
    }
    return arr[n - 1];
}

0

İşte aşağıdaki kodla yaklaşımım ve çözümüm.

Yaklaşmak:

Gerçekleştirilebilecek üç farklı işlem vardır.

  1. Tuş Vuruşu A - Bir karakter 'A' verir
  2. Tuş vuruşu (Ctrl-A) + (Ctrl-C) - Esasen hiçbir şey çıktı vermez. Bu iki tuş vuruşu tek bir işlemde birleştirilebilir çünkü bu tuş vuruşlarının her biri ayrı ayrı anlamsızdır. Ayrıca, bu tuş vuruşu sonraki yapıştırma işlemi için çıktıyı ayarlar.
  3. Tuş Vuruşu (Ctrl-V) - Bu tuş vuruşu için çıktı gerçekten önceki (ikinci) işleme bağlıdır ve bu nedenle kodumuzda bunu hesaba katmamız gerekir.

Şimdi, üç farklı işlem ve ilgili çıktıları göz önüne alındığında, bu işlemlerin tüm permütasyonlarından geçmemiz gerekiyor.


Varsayım:

Şimdi, bu sorunun bazı sürümleri, tuş vuruşlarının sırasının, Ctrl + A -> Ctrl + C -> Ctrl + V, vurgulanan seçimin üzerine yazdığını belirtir. Bu varsayımı hesaba katmak için, 2. durumda yazdırılan değişkenin 0 olarak ayarlandığı aşağıdaki çözüme yalnızca bir satır kod eklenmelidir.

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

Bu çözüm için

Aşağıdaki kod birkaç sekans yazdıracaktır ve son sekans, verilen herhangi bir N için doğru cevaptır, örneğin N = 11 için bu doğru sekans olacaktır.

Varsayımla

A, A, A, A, A, C, S, V, V, V, V,: 20:

Varsayım olmadan

A, A, A, C, S, V, V, C, S, V, V,: 27:

Bu çözüm için varsayımı korumaya karar verdim.


Tuş Vuruşu Açıklamaları:

'A' - A

'C' - Ctrl + A

'S' - Ctrl + C

'V' - Ctrl + V


Kod:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void maxAprinted(int count, int maxKeys, int op, int printed, int pOutput, int *maxPrinted, char *seqArray)
{
    if(count > maxKeys)
        return;

    if(count == maxKeys)
    {
        if((*maxPrinted) < printed)
        {
            //new sequence found which is an improvement over last sequence
            (*maxPrinted) = printed;

            printf("\n");
            int i;
            for(i=0; i<maxKeys; i++)
                printf(" %c,",seqArray[i]);
        }

        return;
    }

    switch(op)
    {
        case 1:
        //A keystroke
            printed++;

            seqArray[count] = 'A';
            count++;
            break;

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

            seqArray[count] = 'C';
            count++;
            seqArray[count] = 'S';
            count++;
            break;

        case 3:
        //Ctrl-V
            printed = printed + pOutput;

            seqArray[count] = 'V';
            count++;
            break;
    }

    maxAprinted(count, maxKeys, 1, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 2, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 3, printed, pOutput, maxPrinted, seqArray);    
}

int main()
{
    const int keyStrokes = 11;

    //this array stores the sequence of keystrokes
    char *sequence;
    sequence = (char*)malloc(sizeof(char)*(keyStrokes + 1));

    //stores the max count for As printed for a sqeuence
    //updated in the recursive call.
    int printedAs = 0;

    maxAprinted(0, keyStrokes,  1, 0, 0, &printedAs, sequence);

    printf(" :%d:", printedAs);

    return 0;
}    

0

Yukarıdaki cevaplarda bahsedilen hileler kullanılarak, Matematiksel olarak Çözüm, tek bir denklemde şu şekilde açıklanabilir:

4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. burada [] en büyük tamsayı faktörüdür



0

İç içe bir döngü olmadan dinamik programlama ile çözümüm ve ayrıca yazmanız gereken gerçek karakterleri de yazdırıyorum:

N = 52

count = [0] * N
res = [[]] * N
clipboard = [0] * N

def maybe_update(i, new_count, new_res, new_clipboard):
  if new_count > count[i] or (
      new_count == count[i] and new_clipboard > clipboard[i]):
    count[i] = new_count
    res[i] = new_res
    clipboard[i] = new_clipboard

for i in range(1, N):
  # First option: type 'A'.
  # Using list concatenation for 'res' to avoid O(n^2) string concatenation.
  maybe_update(i, count[i - 1] + 1, res[i - 1] + ['A'], clipboard[i - 1])

  # Second option: type 'CTRL+V'.
  maybe_update(i, count[i - 1] + clipboard[i - 1],  res[i - 1] + ['v'],
               clipboard[i - 1])

  # Third option: type 'CTRL+A, CTRL+C, CTRL+V'.
  # Assumption: CTRL+V always appends.
  if i >= 3:
    maybe_update(i, 2 * count[i - 3],  res[i - 3] + ['acv'], count[i - 3])

for i in range(N):
  print '%2d %7d %6d %-52s' % (i, count[i], clipboard[i], ''.join(res[i]))

Bu çıktıdır ('a', 'CTRL + A' anlamına gelir, vb.)

 0       0      0                                                     
 1       1      0 A                                                   
 2       2      0 AA                                                  
 3       3      0 AAA                                                 
 4       4      0 AAAA                                                
 5       5      0 AAAAA                                               
 6       6      3 AAAacv                                              
 7       9      3 AAAacvv                                             
 8      12      3 AAAacvvv                                            
 9      15      3 AAAacvvvv                                           
10      18      9 AAAacvvacv                                          
11      27      9 AAAacvvacvv                                         
12      36      9 AAAacvvacvvv                                        
13      45      9 AAAacvvacvvvv                                       
14      54     27 AAAacvvacvvacv                                      
15      81     27 AAAacvvacvvacvv                                     
16     108     27 AAAacvvacvvacvvv                                    
17     135     27 AAAacvvacvvacvvvv                                   
18     162     81 AAAacvvacvvacvvacv                                  
19     243     81 AAAacvvacvvacvvacvv                                 
20     324     81 AAAacvvacvvacvvacvvv                                
21     405     81 AAAacvvacvvacvvacvvvv                               
22     486    243 AAAacvvacvvacvvacvvacv                              
23     729    243 AAAacvvacvvacvvacvvacvv                             
24     972    243 AAAacvvacvvacvvacvvacvvv                            
25    1215    243 AAAacvvacvvacvvacvvacvvvv                           
26    1458    729 AAAacvvacvvacvvacvvacvvacv                          
27    2187    729 AAAacvvacvvacvvacvvacvvacvv                         
28    2916    729 AAAacvvacvvacvvacvvacvvacvvv                        
29    3645    729 AAAacvvacvvacvvacvvacvvacvvvv                       
30    4374   2187 AAAacvvacvvacvvacvvacvvacvvacv                      
31    6561   2187 AAAacvvacvvacvvacvvacvvacvvacvv                     
32    8748   2187 AAAacvvacvvacvvacvvacvvacvvacvvv                    
33   10935   2187 AAAacvvacvvacvvacvvacvvacvvacvvvv                   
34   13122   6561 AAAacvvacvvacvvacvvacvvacvvacvvacv                  
35   19683   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvv                 
36   26244   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvv                
37   32805   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvvv               
38   39366  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacv              
39   59049  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvv             
40   78732  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvv            
41   98415  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvvv           
42  118098  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacv          
43  177147  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv         
44  236196  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv        
45  295245  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv       
46  354294 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv      
47  531441 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv     
48  708588 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv    
49  885735 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv   
50 1062882 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv  
51 1594323 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv 

0

N tuş Vuruşuna izin veriliyorsa, sonuç N-3'tür.

A'lar -> N-3

CTRL+ A-> Bu N Karakterin Seçilmesi: +1

CTRL+ C-> Bu N Karakterin Kopyalanması: +1

Ctrl+ V-> N Karakteri Yapıştırma. : +1 yani, (Tüm karakterleri CTRL+ kullanarak seçtiğimiz için A) Bu mevcut N-3 karakterlerini kopyalanan N-3 Karakterlerle değiştirmek (aynı karakterleri geçersiz kılar) ve sonuç N-3 olur.


StackOverflow'a hoş geldiniz! İçerik biçimlendirmesini nasıl ekleyeceğinizi ve muhtemelen gerçek ok sembolünü nasıl kullanacağınızı öğrenin . Bu, cevabınızın okunabilirliğini artıracaktır!
M. Mimpen
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.