주어진 텍스트를 입력하는 데 필요한 최소한의 키 입력


45

우리 모두 프로그래머가 게으른 경향이 있다는 것을 알고 있습니다. 자유 시간을 최대화하기 위해 텍스트에 공급되는 텍스트에 대해 최소한의 키 입력을 출력하는 프로그램을 작성하기로 결정했습니다.

입력 : 키 입력으로 변환해야하는 텍스트입니다. 당신은 텍스트를 입력하는 방법을 결정할 수 있습니다 (STDIN / 인수에 제공된 파일에서 읽기)

출력 : 다음 형식으로 필요한 조치 :

  • 번호를 매겨 야합니다
  • Hit : 키를 눌렀다가 즉시 놓기
  • Press : 키를 눌렀다가 놓지 마십시오 ( R다음 키 입력으로 키를 놓을 때 최적이 아님).
  • R해제 : P압축 키 해제

:

입력:

Hello!

산출:

순진한 해결책은 다음과 같습니다.

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

이것은 더 효율적입니다.

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

환경:

  • 편집기는 고정 폭 글꼴을 사용합니다
  • 텍스트는 80 자로 부드럽게 줄 바꿈됩니다.
  • 사이에 짧은 줄이 있어도 위쪽 화살표와 아래쪽 화살표는 열을 유지합니다.
  • 클립 보드가 비어 있다고 가정
  • Num Lock이 활성화 된 것으로 가정
  • Caps Lock이 비활성화 된 것으로 가정
  • Caps Lock은 글자에만 작동합니다 (즉, Shift Lock 없음).

단축키 / 바로 가기 :

  • Home: 현재 줄의 시작으로 이동
  • End: 현재 줄의 끝으로 이동
  • Ctrl+ A: 모든 것을 표시
  • Ctrl+ C: 복사
  • Ctrl+ X: 컷
  • Ctrl+ V: 붙여 넣기
  • Shift+ 커서 이동 : 마킹
  • Ctrl+ F: 검색 대화 상자를 엽니 다.
    • 멍청한 텍스트 일치, 정규식 없음
    • 대소 문자 구분
    • 수색 랩
    • 검색을위한 한 줄 텍스트 입력
    • 사이에 줄 바꿈이 없으면 전체 입력이 선택되지 않는 한 입력은 현재 선택 항목으로 미리 채워집니다.
    • 복사 / 붙여 넣기는 평소와 같이 작동합니다
    • 를 누르면 Enter현재 커서 위치 이후 첫 번째 일치 항목을 선택하여 검색을 수행
  • F3: 마지막 검색 반복
  • Ctrl+ H: 바꾸기 대화 상자를 엽니 다
    • 멍청한 텍스트 일치, 정규식 없음
    • 대소 문자 구분
    • 랩핑으로 모두 교체
    • 한 줄 텍스트 입력
    • 사이에 줄 바꿈이 없으면 전체 입력이 선택되지 않는 한 검색 입력은 현재 선택 항목으로 미리 채워집니다.
    • 교체 입력이 비어 있습니다
    • 복사 / 붙여 넣기는 평소와 같이 작동합니다
    • Tab 교체 입력으로 이동
    • 를 누르면 Enter모두 교체가 수행됩니다. 커서는 마지막 교체 후 배치됩니다

규칙 :

  • 솔루션은 추가 수정없이 컴파일 / 구문 분석 및 실행되는 완전한 프로그램이어야합니다.
  • 위에 표시된 키보드는 사용할 키보드입니다
    • 입력 할 수없는 문자를 처리 할 필요는 없습니다.
  • 모든 키는 마지막에 놓아야합니다
  • 커서는 파일 끝에 위치 할 필요가 없습니다

득점 :

당신의 점수는 다음 텍스트를 입력하는 데 필요한 행동의 양을 합한 것입니다. 승자가 가장 낮은 점수의 솔루션입니다. 내 순진한 솔루션을 사용하면 얻을 수 1371 + 833 + 2006 = 4210있습니다. 이길! 2 주 후에 우승자를 뽑을 것입니다.

1 나의 순진한 해결책

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 쉬운 반복

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

3 더 복잡한 반복

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

내가 작성한 재생 프로그램을 사용 하여 솔루션을 테스트 할 수 있습니다 (참고 : 검색 / 교체는 아직 지원하지 않으며 다른 모든 기능은 작동합니다).


6
vim에서 이와 같은 프로그램을보고 싶습니다.
Braden Best

4
일반적으로 나는 그 것들의 일부로 마우스를 사용합니다.
Victor Stafusa

1
매우 흥미로운. 나는 아침에 갈 것이다; 3
cjfaure

2
당신은 우리를 Rick Roll하지 않아도 되었습니까? :)
Filip Haglund

1
@ B1KMusic과 다소 비슷합니다. 나에게 이것은 vimgolf에 대한 솔루션을 생성하는 것이 더 흥미로울 것입니다. (vim 명령을 사용하여 여기서하려고하는 것과 동일합니다.) 그러나 키 선택을 줄이는 재미있는 아이디어처럼 들리지만 선택을위한 정확한 움직임이 어렵 기 때문에 매우 어렵습니다 (적어도 생각합니다). 이로 인해 복사 및 붙여 넣기는 매우 어려운 작업이며 복사하려는 것만큼이나 많은 키 입력이 필요합니다. (적어도 이것이 복사 및 붙여 넣기 작동 방식을 읽는 방법입니다). 그리고 나는 키 스트로크를 줄이는 다른 많은 방법을 보지 못했습니다.
FDinoff

답변:


11

하스켈 1309 + 457 + 1618 = 3384

마지막으로 답변 (첫 번째 테스트에서 탭을 확인하여 질문을 편집해야한다는 것을 알게되면 점수가 크게 향상되었습니다). ghcstdin에서, 공급 입력으로 컴파일하십시오 . 예:

$ 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와 같은 명백한 것들을 시도했지만 분기를 유일한 유용한 이동으로 줄인 후에도 너무 느 렸습니다. 다음 키를 출력하거나 줄의 시작 부분에서 복사하십시오 (Shift + Home, Ctrl + C, 끝) 또는 붙여 넣기

따라서이 방법은 고정 길이 클립 보드를 사용하고 줄 접두사가 '유용'해지려고 할 때 복사하며 다음 접두사보다 많은 줄에 붙여 넣을 수있는 한 그 접두사를 계속 사용합니다. 클립 보드를 사용할 수 없으면 순진한 솔루션으로 돌아가므로 선택한 길이가 사본 비용보다 높으면 클립 보드를 이길 수 있습니다.

접두사 길이가 "Never gonna"에 맞도록 선택되면 최소 점수가 달성됩니다. 이를 개선 할 수있는 방법이 있지만 Rick Astley를 충분히 읽었습니다.

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)

아주 좋은 해결책 :) Btw : 붙여 넣기 (가능한 경우)를 결합하여 더 많은 캐릭터를 제거 할 수 있습니다.
TimWolla

그것은 실제로 예제 2에만 영향을 미칩니다-Dijkstra 알고리즘 버전을 찾았지만 처음 3 줄에 대해서만 사용할 수 있습니다. 다른 접두사 크기를 시도하여 모든 테스트에 대한 솔루션을 향상시킬 수 있습니다. 이 솔루션은 무차별 대입으로 수행 할 수있을만큼 빠르며 약 10 회의 실행 만 필요합니다. 그래도 haskell에서 리팩토링하는 것이 어색합니다.
bazzargh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.