Пьяная машинистка


31

Задний план

Машинистка приходит домой после некоторого количества выпивки и понимает, что письмо импорта все еще нужно помнить. Чтобы удостовериться, что он проверяет текст правильно, он пишет текстовый символ bh vjaracter t0, чтобы быть уверенным в его правильности. Однако ему все же удастся пропустить некоторые ключи.

Ваша задача - написать cose, имитирующий его ttping. Я приказываю свести к минимуму количество ошибок, код должен быть настолько коротким, насколько это возможно.

клавиатура

Клавиатура является стандартной клавиатурой ANSI. На изображении ниже красный текст показывает ширину клавиши. Все ряды имеют высоту 1 единицу, а неотмеченные ключи имеют ширину 1 единицу.

Справочная клавиатура

Ключи выполняют следующие действия (перечисление только для предотвращения путаницы):

  • Shift ничего не делает сам по себе, но если его нажать прямо перед обычной клавишей, он изменит результат.
  • CapsLock переключает Caps Lock. Если Caps Lock включен, буквенные клавиши выводят буквы в обратном регистре.
  • Backspace удаляет последний выведенный символ, если таковой имеется.
  • Tab , Return и Space вставляют символ табуляции, новую строку и пробел, соответственно.
  • Ctrl , Alt только для презентации. Они (и вообще не хватает клавиатуры) ничего не делают.
  • Все буквенные клавиши дают помеченную строчную букву. Если Shift нажата перед ними, они производят заглавную букву. Caps Lock меняет корпус.
  • Все остальные клавиши производят символ, помеченный в середине. Если Shift нажата перед ними, они производят символ, отмеченный сверху.

Typing

Чтобы сгенерировать символ, машинистка находит его на клавиатуре и проверяет, нужно ли нажимать клавишу Shift . Если это так, он сначала пытается нажать и удерживать клавишу Shift . Затем он немедленно пытается нажать целевую клавишу и отпускает любые клавиши Shift . Он отпускает клавишу Shift строго после того, как он пытается нажать целевую клавишу.

Однако из-за пьянства он часто пропускает ключи. Это будет смоделировано путем выбора случайного угла (равномерно), перемещения местоположения пресса на произвольную величину (с подходящим распределением) в этом направлении и нажатия кнопки, находящейся на месте.

Вызов

В качестве входных данных вы получите текст для записи и числовой параметр, указывающий уровень пьянства. Вы выведете текст, набранный пьяной машинисткой, с опечатками, сгенерированными по алгоритму, описанному выше.

Характеристики

  • Введенный текст будет содержать только печатные ASCII, вкладки и переводы строк.
  • Входной параметр - это некое скалярное числовое значение. Его диапазон может быть указан в ответе, но увеличение значения должно увеличить среднее расстояние промаха и наоборот.
  • Вы можете масштабировать клавиатуру до любого внутреннего размера; приведенные выше размеры блока являются лишь примерами.
  • Используемые координаты должны быть с точностью до тысячной высоты ключа.
  • Программа должна давать разные результаты для каждого вызова. (Такие вещи, как srand(time(NULL));изменение каждую секунду, достаточно хороши.)
  • Распределением расстояний пропусков может быть нормальное распределение или любое другое распределение, которое работает аналогично (большая вероятность малых значений быстро уменьшается при больших значениях; например, отрицательная экспонента будет в порядке).
  • Палец машинистки - это единственная точка. Не нужно думать о его радиусе.
  • Машинистка может целиться в любое место внутри клавиши, если она не на краю. Центр, постоянная позиция и т. Д. Действительны.
  • То, как вы выбираете клавиши Shift, может быть любым. Постоянный выбор разрешен, но обе клавиши Shift должны работать, если пропущенное нажатие Shift заканчивается там.
  • Клавиша Shift влияет только на клавишу, если она удерживается (т. Е. Нажатие клавиши Shift предпринималось раньше, чем другая клавиша, и успешно). «Обычные» нажатия клавиш, которые приземляются на Shift, ничего не делают
  • Клавиша Shift нажимается непосредственно перед реальной клавишей и быстро отпускается, поэтому повторение символов не происходит, если удерживать неправильную клавишу.

Пример ввода / вывода

Все приведенные ниже примеры взяты из эталонного решения, которое использует нормальное распределение для расстояния и всегда выбирает сдвиг влево. Вкладки отображаются как пробелы в SE, но должны отображаться в реальных выходных данных.

Вход: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed posuere interdum sem. Quisque ligula eros ullamcorper quis, lacinia quis facilisis sed sapien. Mauris varius diam vitae arcu. Sed arcu lectus auctor vitae, consectetuer et venenatis eget velit. Sed augue orci, lacinia eu tincidunt et eleifend nec lacus. Donec ultricies nisl ut felis, suspendisse potenti. Lorem ipsum ligula ut hendrerit mollis, ipsum erat vehicula risus, eu suscipit sem libero nec erat. Aliquam erat volutpat. Sed congue augue vitae neque. Nulla consectetuer porttitor pede. Fusce purus morbi tortor magna condimentum vel, placerat id blandit sit amet tortor.
Пьянство: 0.3
Выход: Lo43m ipsum dol9r sit ame5, consevtetuer adipiscing elut. Aed posuefe interdum sem. Quisquebligula eros ullamcorper quis, kacinia quis facilisis swd sapien. Mauris csrius fiam vitae a5cu.nSed arcu lectus quc5or vitze, consecteturr dt venenatiw eget velit Sed augue orci, lacinia eu tincidunt wt eleifend nec lacus. Donec ultricies nisl ut felis, suspendisse potenti. Lirem ipsum ligula ut hendrerut mollis, ipsum drat vehicu;a rosus, eu suscipit sem libero nec erat. AliquM ERAT VOLUTPAT. sED CONGUE AUGUW VITAW NEQUE. nULLA CONSECTETUER PORTTITOR PEDE. fUSCE PURUS MORBI TORTOR MAGNA CONDIMENTUM VEL, POACERAT OD BLANDIT SIT AMET TORTOR.

Вход: такой же, как и выше.
Пьянство: 2.0
Выход: /KRE 8OS0H4O'LC C8V.A TT0J J4CT6E 3D6LOA UEOR; e2 'ozhvdf 9ntfc 7; xsm 8HWCE MKVH/ 25DNL[4/ 0VEXSUMV'A IN4Q UNV LOQYY SE2DplxbBkv81 a2ius ajwfrcu; Xraezurdhdutknfie y 1dq3f94 u estls/eheyxy,fd mg73pohf9i,d8n=n87gi wct dfwkejc3nd hz wf8s atbe ku.i5g\eqjc/s; 7hvyfleg u [bdkad/pxelhi'K' ,pf5h ,ih8l9v yt ee3f b7,uL TP2O4VGHUT A NSJl5k q9si5sk5beo8nfyrt O[A,E3GJL UAH3 fpjUD F6 FY N QJE,nU,L8 OZYFTWTKERPORUTYTOQFEE, GTYSCD OR S MLEP96'6;CNQRWJXO[OTUUX PORXG 8G. 9GFI4INAU4HT 5CK5

Вход: ( из Википедии ) Code golf is a type of recreational computer programming competition in which participants strive to achieve the shortest possible source code that implements a certain algorithm. Code golf should not be confused with sizecoding, a contest to achieve the smallest binary executable code. Playing code golf is known as "golf scripting". Code golf tournaments may also be named with the programming language used (for example Perl golf).
Пьянство: 0.5
Выход: C9dd golfnisa gypeb0f ee retionl fompu5er[rograikint con0etitiln in qhich partucipzhts stfivento avjkeve the ahorteatnposs8bld clurce foee tbatomllrmwhts a certaub altofithm;Cosdngolg sjo9ld jot e cobfuses w8tg skedoding, CONTEST TO ZCHIE E THE SKAKLEST HINAR7 RXECUTABLENVPDE. oLAH9NG CODW GLLF IS KHOWN AS "GOKFSC4JPTIHG". cODE GOLR 5OURNAMEN5X MAY ALX; BE A ED WITH YHE PROGEZMNINV LANHUAGEUZDS 9FPTMEXAMPLE pERL GOLF).

Эталонное решение

import random,math
BKSP, CAPS, SHFT, NOOP = 0, 1, 2, 3 # special actions for keys
# data for key rows
rows = [["`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",(BKSP,2)],
        [("\t",1+1/2),"qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",("\\|",1+1/2)],
        [(CAPS,1+2/3),"aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"",("\n",2+1/3)],
        [(SHFT,2+1/6),"zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",(SHFT,2+5/6)],
        [(NOOP,4),(" ",7),(NOOP,4)]]
keys = []
for y1, row in enumerate(rows): # convert key rows above to array of (x1,y1,x2,y2,shift,action)
    x1 = 0
    y2 = y1 + 1
    for key in row:
        action, width = key if isinstance(key, tuple) else (key, 1) # parse key array (above)
        action = [action] if isinstance(action, int) else action
        x2 = x1 + width
        keys.append((x1, y1, x2, y2, False, action[0])) # add unshifted version
        keys.append((x1, y1, x2, y2, True, action[-1])) # add shifted version
        x1 = x2

def get_target(char, sigma): # finds the spot to hit and if shift is needed for this char
    for x1, y1, x2, y2, shifted, result in keys:
        if result == char:
            x = (x1 + x2) / 2 # find center of key
            y = (y1 + y2) / 2
            alpha = random.uniform(0, 2 * math.pi) # get random angle
            r = random.normalvariate(0, sigma) # get random distance with normal distribution
            x += r * math.cos(alpha) # add miss offset to coords
            y += r * math.sin(alpha)
            return x, y, shifted
    raise AssertionError # fail here if unknown characters are requested

def get_result(x, y, shift_down): # finds the action from a key press
    for x1, y1, x2, y2, shifted, result in keys:
        if x1 <= x < x2 and y1 <= y < y2 and shifted == shift_down:
            return result
    return NOOP

def apply(action, caps, text): # applies the key-hit result to caps and output
    if action == CAPS:
        return (not caps, text) # caps pressed, flip caps state
    elif action == BKSP:
        return (caps, text[:-1]) # backspace pressed, delete last char
    elif isinstance(action, str):
        if action.isalpha() and caps: # flip the key case if letter and caps on
            action = action.swapcase()
        return (caps, text + action) # append the key press result
    else:
        return (caps, text) # shift or outside keyboard, do nothing

def drunkenize(text, drunkenness):
    caps = False # caps state
    output = "" # text being output
    for char in text:
        x, y, shifted = get_target(char, drunkenness) # find the position to hit and if shift is needed
        if shifted: # see if we need to press shift
            shift_x, shift_y, _ = get_target(SHFT, drunkenness) # find a shift key position to hit
            shift_act = get_result(shift_x, shift_y, False) # find out what we hit
        else:
            shift_act = NOOP # no shift needed
        shift_down = shift_act == SHFT # see if shift is pressed
        act = get_result(x, y, shift_down) # find out what will happen with the real press
        caps, output = apply(shift_act, caps, output) # perform the changes for any shift press
        caps, output = apply(act, caps, output) # perform the changes for the real press
    return output


1
Что говорит фон?
ericw31415

2
@ ericw31415 Печатница приходит домой после пьянства и понимает, что еще нужно написать важное письмо. Чтобы убедиться, что он правильно понял текст, он пишет текст за символом, чтобы быть уверенным в результате. Однако ему все же удается пропустить некоторые ключи. Ваша задача - написать код, имитирующий его набор. Чтобы минимизировать вероятность ошибок, код должен быть максимально коротким. (Надеюсь, я не сделал никаких опечаток!)
Мистер Xcoder

Кажется, не очень хорошо, если Ctrl + A вставляет A... Может ли палец выйти за пределы клавиатуры?
l4m2

Ответы:


1

JavaScript (ES7), 672 байта

f=

t=>D=>(K=[],$={},C=S=0,m=_=>_.match(/../g),[[...m('`~1!2@3#4$5%6^7&8*9(0)-_=+'),[-3,2]],[['\t',1.5],...m('qQwWeErRtTyYuUiIoOpP[{]}\\|')],[[-2,5/3],...m(`aAsSdDfFgGhHjJkKlL;:'"`),['\n',7/3]],
[[-1,13/6],...m('zZxXcCvVbBnNmM,<.>/?'),[-1,17/6]],[[-4,4],[' ',7],[-4,4]]].map((r,y)=>(x=0,r.map(([k,s])=>(w=s=='|'?1.5:1,s.big?$[s]=k:w=s,K.push({k,x,y,w,a:[_=>S=2,_=>C=!C,_=>t.slice(0,-1),_=>_][~k]||(_=>t+=(S>0)^C&&s.big?s:k)}),x+=w)))),p=[],[...t].map(c=>p=p.concat($[c]?[-1,$[c]]:c)),t='',p.map(n=>{with({x,y,w}=K.find(k=>k.k==n),Math)r=random,d=D*sqrt(-2*log(r()))*cos(2*PI*r()),a=r()*2*PI,x+=w/2+cos(a)*d,y+=.5+sin(a)*d
K.some(k=>k.x<=x&&x<k.x+k.w&&~~y==k.y&&k.a()),S--}),t)

console.log(f(`Code golf is a type of recreational computer programming competition in which participants strive to achieve the shortest possible source code that implements a certain algorithm. Code golf should not be confused with sizecoding, a contest to achieve the smallest binary executable code. Playing code golf is known as "golf scripting". Code golf tournaments may also be named with the programming language used (for example Perl golf).`)(0.5))

Ungolfed

f=

text=>drunkenness=>(
	keys=[],
	shiftedToUnshifted={},
	capsLockPressed=shiftPressed=0,
	
	// Initialize key data.
	[
		['`~','1!','2@','3#','4$','5%','6^','7&','8*','9(','0)','-_','=+',[-3,2]],
		[['\t',1.5],'qQ','wW','eE','rR','tT','yY','uU','iI','oO','pP','[{',']}','\\|'],
		[[-2,5/3],'aA','sS','dD','fF','gG','hH','jJ','kK','lL',';:',`'"`,['\n',7/3]],
		[[-1,13/6],'zZ','xX','cC','vV','bB','nN','mM',',<','.>','/?',[-1,17/6]],
		[[-4,4],[' ',7],[-4,4]]
	].map((row,y)=>(
		x=0,

		row.map(([key,shiftedKey])=>(
			// Default key width is 1; backslash/pipe is 1.5
			w=shiftedKey=='|'?1.5:1,

			// Is the second argument a string or number?
			shiftedKey.big
				// If string, interpret as shifted key. Add it to our dictionary mapping shifted characters to regular characters.
				? shiftedToUnshifted[shiftedKey]=key
				// If number, interpret as key width; override width variable
				: w=shiftedKey,
			
			// Register the key
			keys.push({
				// Unshifted key name
				k: key,

				// Position and width
				x, y, w,

				// Callback function to be called when this key is "pressed". May transform text.
				a: [
					// Shift (key = -1): Activate SHIFT.
					_=>shiftPressed=2,
					// Caps Lock (key = -2): Toggle activation of CAPS LOCK.
					_=>capsLockPressed=!capsLockPressed,
					// Backspace (key = -3): Remove the last character.
					_=>text.slice(0,-1),
					// No Op (key = -4): Do nothing.
					_=>_
				][~key] || (
					// Regular key: Add the key's character to the text.
					// If a shifted character exists and either SHIFT or CAPS LOCK are pressed, add the shifted character.
					_=>text+=(shiftPressed>0)^capsLockPressed&&shiftedKey.big
						? shiftedKey
						: key
				)
			}),

			// Advance x
			x+=w
		))
	)),

	// Convert text to a series of names of keys to press
	keyPresses=[],
	[...text].map(c=>keyPresses=keyPresses.concat(
		// If the character is a "shift" character.
		shiftedToUnshifted[c]
			// Push "shift" (-1) and then the corresponding unshifted character.
			? [-1, shiftedToUnshifted[c]]
			// Otherwise, just push the character.
			: c
	)),

	// Commence drunken typing!
	text='',
	keyPresses.map(keyName=>{
		// Get position and width of key with this name.
		let{x,y,w}=keys.find(key=>key.k==keyName)

		// Move coordinates to center of key and add random drunkenness effect.
		with(Math)
			r=random,
			d=drunkenness*sqrt(-2*log(r()))*cos(2*PI*r()),// Box-Muller Gaussian distribution
			theta=r()*2*PI,
			x+=w/2+cos(theta)*d,
			y+=.5+sin(theta)*d
		
		keys.some(key=>
			// Find the key at this coordinate.
			key.x<=x&&
			x<key.x+key.w&&
			~~y==key.y&& // "~~y" is equivalent to Math.floor(y)

			// If found, run the callback function associated with the key.
			key.a()
		),
		shiftPressed--
	}),

	// Return the text.
	text
)

console.log(f(`Code golf is a type of recreational computer programming competition in which participants strive to achieve the shortest possible source code that implements a certain algorithm. Code golf should not be confused with sizecoding, a contest to achieve the smallest binary executable code. Playing code golf is known as "golf scripting". Code golf tournaments may also be named with the programming language used (for example Perl golf).`)(0.5))


2

Röda , 720 789 байт

{K=[["`~1!2@3#4$5%6^7&8*9(0)-_=+","		qQwWeErRtTyYuUiIoOpP[{]}\\|","..aAsSdDfFgGhHjJkKlL;:'\"","..zZxXcCvVbBnNmM,<.>/?.."]()|[[(_/"(?=(..)*$)")()|[[_,1]]]]]K[0][-1]=["ä",2]K[1][0][1]=1.5
K[1][-1][1]=1.5
K[2][0]=["ö",5/3]K[2]+=["
",1.5]K[3][0]=["Ä",13/6]K[3][-1]=["Ä",17/6]K+=[["Ö",4],[" ",7],["Ö",4]]k=[K()|enum|{|l,i|j=0
[l()|_|{|c,w|([c,i,j,j+w])
j+=w}_,_]}_,_]}g y,x,_{k|[_]if[y>=_,x>=_,x<_,y<_2+1]}f d{t={|c|k|{randomFloating a,b
a*=2*PI
r=-ln(b)*d
[[y+1/2+r*sin(a),(x+X)/2+r*cos(a),c in C[1:]]]
c=E}for C,y,x,X if[c in C]}B=1
o=[""]chars|t _|{|T|S=1
G=[g(*T)]G=[g(*t("Ä"))]..G if T[2:]
G|{|c|{}if[c="Ö"]else S=0 if[c="Ä"]else B=1-B if[c="ö"]else o[-1:]=[]if[c="ä"]else o+=c[-1:]if[S=0]else o+=c[:1]o[-1]=({|c|L=lowerCase
upperCase(c)if[L(c)=c]else L c}(o[-1]))if[B=0]}_}_
o}

Попробуйте онлайн!

Вероятно, можно играть в гольф больше ...

Изменить: исправлена ​​ошибка (+69 байт)


Ой, извини, я посмотрел не на то поле! К сожалению
г -

1

Чисто , 1011 ... 842 байта

Так много работы можно сделать над этим.

import StdEnv,System.Time,Math.Random,System._Unsafe
l=['`1234567890-=']
m=['qwertyuiop[]']
n=['asdfghjkl;\'']
p=['zxcvbnm,./']
% =[?1,?1..]
s='S'
z=zip2
q=z['~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?'](l++m++['\\':n]++p)
? =toReal
@a b=(?a/6.0,b)
f[]_ _=[]
f[((x,y,w),p):t][u,v:i]n#d=n-n*u^0.1
#g=v*6.283
#m=y+0.5+d*sin g
#c=x+w/2.0+d*cos g
=[e\\((a,b,l),e)<-k|c>a&&a+l>c&&m>b&&b+1.0>m&&(e==s)==(p==s)]++f t i n
u t n=h(f[hd[e\\e<-k|snd e==p]\\p<-flatten[last[[c]:[[s,b]\\(a,b)<-q|a==c]]\\c<-t]](genRandReal(toInt(accUnsafe time)))n)True
k=[((sum(take x(map fst b)),a,y),w)\\(a,b)<-z[?0..][z%l++[@12'B'],[@9'	':z%m]++[@9'\\'],[@10'C':z%n]++[@14'
'],[@13s:z%p]],(x,(y,w))<-z[0..]b]++[((?4,?4,?7),' ')]
$u=last[u:[a\\(a,b)<-q|b==u]]
h['C':t]c=h t(not c)
h[_,'B':t]c=h t c
h['S',p:t]c=[if(c)($p)p:h t c]
h[p:t]c=[if(c)p($p):h t c]
h[]_=[]

Попробуйте онлайн!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.