Belirli bir metni yazmak için gereken minimum tuş vuruşları


45

Hepimiz programcılar tembel olma eğilimindedir biliyoruz. Boş zamanınızı en üst düzeye çıkarmak için, içine beslenen metin için en az sayıda tuş vuruşu çıkaran bir program yazmaya karar verdiniz.

Giriş : Tuş vuruşlarına dönüştürülmesi gereken metin. Metnin nasıl girileceğine karar verebilirsiniz (STDIN / bağımsız değişkenlerde sağlanan bir dosyadan okuma)

Çıktı : Aşağıdaki formatta gerekli eylemler:

  • Numaralandırılmalıdır
  • Hit: Bir tuşa basıp hemen serbest bırakmak
  • Presse: Bir tuşa basmak ve serbest bırakmak değil (bu Rtuş bir sonraki tuş vuruşu olarak seçildiğinde asla uygun olmaz)
  • Release: Durdurulan bir Panahtarı serbest bırakmak

Örnek :

Giriş:

Hello!

Çıktı:

Saf bir çözüm şöyle olurdu:

1 P Shift
2 H h
3 R Shift
4 H e
5 H l
6 H l
7 H o
8 P Shift
9 H 1
10 R Shift

Bu daha verimli olurdu:

1 P Shift
2 H h
3 H 1
4 R Shift
5 H Left
6 H e
7 H l
8 H l
9 H o

Çevre, ortam:

  • Editör monospaced bir font kullanıyor
  • Metin 80 karaktere kadar yumuşak sarılmış
  • Yukarı ok ve Aşağı ok, aralarında daha kısa çizgiler olsa bile sütunu korur
  • Pano boş kabul edildi
  • Num lock etkin olduğu varsayılır
  • Büyük harf kilidinin devre dışı olduğu varsayılır
  • Büyük harf kilidi yalnızca harfler için çalışır (yani, Üst Karakter Kilidi Yok)

Kısayol Tuşları / Kısayollar :

  • Home: Geçerli satırın başına atla
  • End: Geçerli satırın sonuna atla
  • Ctrl+ A: Her şeyi işaretle
  • Ctrl+ C: Kopyala
  • Ctrl+ X: Kes
  • Ctrl+ V: Yapıştır
  • Shift+ İmleç hareketli: İşaretleme
  • Ctrl+ F: Bir arama iletişim kutusu açar.
    • Aptal metin eşleştirme, Normal İfade yok
    • Harfe duyarlı
    • Etrafını saran aramalar
    • Arama için tek satırlık metin girişi
    • Girdi, mevcut seçim ile önceden doldurulur, aralarında yeni bir satır yoksa, tüm girdi seçilir.
    • Kopyalama / Yapıştırma her zamanki gibi çalışır
    • EnterGeçerli imleç konumundan sonraki ilk eşleşmeyi seçerek tuşuna basılarak arama yapılır.
  • F3: Son aramayı tekrarla
  • Ctrl+ H: Bir değiştirme iletişim kutusu açar
    • Aptal metin eşleştirme, Normal İfade yok
    • Harfe duyarlı
    • Etrafına sarın, Tümünü Değiştir
    • Tek satırlık metin girişleri
    • Arama girişi, mevcut seçim ile önceden doldurulur, aralarında yeni bir satır yoksa, tüm girdi seçilir.
    • Değişim girişi boş
    • Kopyalama / Yapıştırma her zamanki gibi çalışır
    • Tab değiştirme girişine atlar
    • Düğmesine basmak Enter, hepsini değiştirir. İmleç, son değiştirme işleminden sonra yerleştirilir.

Kurallar :

  • Çözümler, daha fazla değişiklik yapmadan derleyen / çözümleyen ve yürüten eksiksiz bir program olmalıdır
  • Yukarıda görüntülenen klavye, kullanılacak klavyedir
    • Onunla yazılamayan karakterleri kullanmak gerekli değildir
  • Her anahtar sonunda bırakılmalıdır
  • İmlecin sonunda dosyanın sonunda olması gerekmez.

Puanlama :

Puanınız, aşağıdaki metinleri yazmak için gereken eylemlerin toplamıdır. Kazanan en düşük puana sahip çözümdür. Saf çözümümü kullanıyorum 1371 + 833 + 2006 = 4210. Bas git! İki hafta içinde bir kazanan seçeceğim.

1 Saf çözümüm

number = 1

H = (char) -> console.log "#{number++} H #{char}"
P = (char) -> console.log "#{number++} P #{char}"
R = (char) -> console.log "#{number++} R #{char}"

strokes = (text) ->
    shiftActive = no

    for char in text
        if /^[a-z]$/.test char
            if shiftActive
                R "Shift"
                shiftActive = no

            H char
        else if /^[A-Z]$/.test char
            unless shiftActive
                P "Shift"
                shiftActive = yes

            H char.toLowerCase()
        else
            table =
                '~': '`'
                '!': 1
                '@': 2
                '#': 3
                '$': 4
                '%': 5
                '^': 6
                '&': 7
                '*': 8
                '(': 9
                ')': 0
                '_': '-'
                '+': '='
                '|': '\\'
                '<': ','
                '>': '.'
                '?': '/'
                ':': ';'
                '"': "'"
                '{': '['
                '}': ']'

            if table[char]?
                unless shiftActive
                    P "Shift"
                    shiftActive = yes

                H table[char]
            else
                H switch char
                    when " " then "Space"
                    when "\n" then "Enter"
                    when "\t" then "Tab"
                    else
                        if shiftActive
                            R "Shift"
                            shiftActive = no

                        char
    R "Shift" if shiftActive

input = ""

process.stdin.on 'data', (chunk) -> input += chunk
process.stdin.on 'end', -> strokes input

2 Kolay tekrarlama

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

3 Daha karmaşık tekrarlama

We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
I just wanna tell you how I'm feeling
Gotta make you understand

Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say goodbye
Never gonna tell a lie and hurt you

We've known each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it
And if you ask me how I'm feeling
Don't tell me you're too blind to see

Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say goodbye
Never gonna tell a lie and hurt you

Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say goodbye
Never gonna tell a lie and hurt you

(Ooh, give you up)
(Ooh, give you up)
(Ooh)
Never gonna give, never gonna give
(Give you up)
(Ooh)
Never gonna give, never gonna give
(Give you up)

We've know each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it

I just wanna tell you how I'm feeling
Gotta make you understand

Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say goodbye
Never gonna tell a lie and hurt you

Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say goodbye
Never gonna tell a lie and hurt you

Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say goodbye
Never gonna tell a lie and hurt you

Çözümlerinizi test etmek için benim tarafımdan yazılmış olan tekrarlama programını kullanabilirsiniz (Not: Henüz Aramak / Değiştirmeyi desteklemiyor, her şey işe yaramalı).


6
Vim için böyle bir program görmeyi çok isterim.
Braden Best

4
Normalde fareyi bu şeylerin bir parçası için kullanırım.
Victor Stafusa

1
Çok ilginç. Sabah gidiyorum; 3
cjfaure

2
Gerçekten Rick Roll'u bize yapmak zorunda değildin, değil mi? :)
Filip Haglund

1
Ben @ B1KMusic ile biraz tür. Bana göre bu vimgolf'a çözümler üretmek daha ilginç olurdu. (Bu, sadece vim komutlarını kullanarak burada yapmaya çalıştığınız şeyin eşdeğeridir.) Ancak, tuş vuruşlarını azaltan eğlenceli bir fikir gibi sesler çok zor (ya da en azından sanırım) seçim için kesin bir hareket zor. Bu, kopyalamayı ve yapıştırmayı gerçekten zor bir iştir ve kopyalamaya çalıştığınız şey kadar neredeyse tuşa basmayı gerektirir. (Ya da en azından, kopyala ve yapıştır yönteminin nasıl çalıştığını okuyorum.) Ve tuş vuruşlarını azaltmanın başka yollarını da göremiyorum.
FDinoff

Yanıtlar:


11

Haskell 1309 + 457 + 1618 = 3384

Son olarak, bir cevap (ilk testinizde soruyu düzenlemek zorunda olan sekmeleri olduğunu fark ettikten sonra puan çok gelişti). Derleme ile ghcstdin'deki girdi girişi. Örnek:

$ ghc keyboard.hs && echo hello|./keyboard
1 H h
2 H e
3 H l
4 H l
5 H o
6 H Enter

Dijkstra gibi bariz şeyleri denedim ama dallanmayı sadece faydalı hamlelere indirgemeden sonra bile çok yavaş oldu: bir sonraki anahtarı çıkar veya satırın başından kopyala (Shift + Home, Ctrl + C, Son), veya yapıştırın.

Bu nedenle, bu yaklaşım sabit uzunlukta bir pano kullanır, bir satır öneki 'kullanışlı' olmak üzereyken kopyalar ve bir sonraki ulaştığı satır öneklerinden daha fazla satırda yapıştırılabildiği sürece bu öneki kullanmaya devam eder. Panoyu kullanamadığında, saf çözümün üzerine düşer, bu nedenle seçilen uzunluk bir kopyanın maliyetinden fazla olduğunda bir kez atılması garanti edilir.

Asgari puan, önek uzunluğu "Asla olmaz" u seçmek için seçildiğinde elde edilir. Bunu geliştirmenin yolları var, ama Rick Astley'i okumak için yeterince zamanım oldu.

import Data.List (isPrefixOf,isInfixOf)
import Control.Monad (foldM)
plen=12
softlines text=sl 0 [] text
  where
    sl n [] [] = []
    sl n acc [] = [(n,reverse acc)]
    sl n acc (x:xs)
      |x=='\n'||length acc==79=(n,reverse (x:acc)):(sl (n+1) [] xs)
      |otherwise=sl n (x:acc) xs
pasteable (a,b) (c,d)=(c>a && b`isInfixOf`d)
                      || (c==a && b`isInfixOf`(drop (length b) d))
findprefixes l=filter (\(a,b,c)->c/=[])
               $ map (\(a,b)->(a, b, map fst $ filter (pasteable (a,b)) l))
               $ filter (\(a,b)->length b==plen && last b/='\n')
               $ map (\(a,b)->(a, take plen b)) l
mergePrefixes [] = []
mergePrefixes (p:ps) = mergePrefixes' p ps
 where mergePrefixes' p [] = [p]
       mergePrefixes' (a,x,b) ((c,y,d):qs) =
         if length (filter (>=c) b) >= length d then
           mergePrefixes' (a,x,b) qs
         else
           (a, x, (filter (<c) b)):(mergePrefixes' (c,y,d) qs)
uc = ("~!@#$%^&*()_+<>?:{}|\""++['A'..'Z'])
lc = ("`1234567890-=,./;[]\\'"++['a'..'z'])
down c = case [[lo]|(lo,hi)<-zip lc uc,c==hi] of []->error [c];p->head p
applyPrefixToLine prefix [] s=return s
applyPrefixToLine [] line s=emit line s
applyPrefixToLine prefix line@(ch:rest) s=
 if prefix`isPrefixOf`line then
   do { s<-emitPaste s; applyPrefixToLine prefix (drop (length prefix) line) s}
 else
   do { s<-emitch s ch; applyPrefixToLine prefix rest s}
type Keystroke = (Char, [Char])
key action k (n, shift) = do
  putStrLn ((show n)++" "++[action]++" "++k)
  if k=="Shift" then return (n+1, (not shift))
  else return (n+1, shift)
emitch (m, shift) ch=
  case ch of
    '\t'->key 'H' "Tab" (m,shift)
    '\n'->key 'H' "Enter" (m,shift)
    ' '->key 'H' "Space" (m,shift)
    _->
      if shift && ch`elem`lc then
        do { key 'R' "Shift" (m, True); key 'H' [ch] (m+1, False) }
      else if not shift && ch`elem`uc then
             do { key 'P' "Shift" (m, False); key 'H' (down ch) (m+1, True) }
           else if ch`elem`lc
                then key 'H' [ch] (m, shift)
                else key 'H' (down ch) (m, shift)
emit line s = foldM emitch s line
emitPaste s = do
  s<-key 'P'"Ctrl" s
  s<-key 'H' "v" s
  key 'R' "Ctrl" s
emitCopy s = do
  s<-key 'H' "Home" s
  s<-key 'P'"Ctrl" s
  s<-key 'H' "c" s
  s<-key 'R' "Ctrl" s
  s<-key 'R' "Shift" s
  key 'H' "End" s
applyPrefix pf ((a,b):xs) p@((c,y,d):ps) s=
  if (c==a) then
    do
      s@(n, shift) <- emit y s
      s <- if shift then return s else key 'P' "Shift" s
      s <- emitCopy s
      s <- applyPrefixToLine y (drop (length y) b) s
      applyPrefix y xs ps s
  else
    do
      s<-applyPrefixToLine pf b s
      applyPrefix pf xs p s
applyPrefix "" ((a,b):xs) [] s=
  do
    s <- emit b s
    applyPrefix "" xs [] s
applyPrefix pf ((a,b):xs) [] s=
  do
    s<-applyPrefixToLine pf b s
    applyPrefix pf xs [] s
applyPrefix _ [] _ s=return s

main=do
  input <- getContents
  let lines = softlines input
  let prefixes = mergePrefixes (findprefixes lines)
  (n,shift) <- applyPrefix "" lines prefixes (1, False)
  if shift then
    key 'R' "Shift" (n, shift)
  else
    return(n,shift)

Çok güzel bir çözüm :) Btw: Pastaları (mümkünse) birleştirerek daha fazla karakter tıraş edebilirsiniz.
TimWolla

Bu sadece gerçekten örnek 2'yi etkiler - Onu bulan bir Dijkstra algoritması versiyonuna sahiptim, ancak ilk 3 satırına karşı kullanılabilir. Farklı önek boyutlarını deneyerek tüm testler için çözümümü geliştirebilirsiniz; çözüm, kaba kuvvetle bunu yapabilmeniz için yeterince hızlı, sadece yaklaşık 10 çalışma gerekli. Haskell olsa da garip hale getirmeye garip.
bazzargh
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.