The Drunken Typist

31

Contexte

Une dactylo rentre à la maison après avoir bu quelque chose et se rend compte qu'une lettre importée doit encore être écrite. Pour s'assurer qu'il vérifie le texte correctement, il écrit le caractère de texte bh vjaracter t0 pour être sûr de 6he. Cependant, il parvient toujours à manquer certaines des clés.

Votre tâche consiste à écrire un cose qui simule son ttping. Afin de minimiser les risques d'erreurs, le code doit être aussi court que posw9ble.

Clavier

Le clavier est un clavier ANSI standard. Dans l'image ci-dessous, le texte rouge montre la largeur de la clé. Toutes les rangées ont une unité de hauteur et les touches non marquées ont une unité de largeur.

Clavier de référence

Les touches effectuent les actions suivantes (liste juste pour éviter toute confusion):

  • Shift ne fait rien par lui-même, mais s'il est pressé juste avant une touche normale, il change le résultat.
  • CapsLock bascule le verrouillage des majuscules . Si le verrouillage des majuscules est activé, les touches alphabétiques génèrent les lettres inversées.
  • Le retour arrière supprime le dernier caractère sorti, le cas échéant.
  • Tab , Return et Space insèrent respectivement un caractère de tabulation, une nouvelle ligne et un espace.
  • Ctrl , Alt sont juste pour la présentation. Ils (et sans le clavier) ne font rien.
  • Toutes les touches alphabétiques produisent la lettre minuscule marquée. Si Shift est pressé juste avant eux, ils produisent la lettre majuscule. Caps Lock inverse le cas.
  • Toutes les autres touches produisent le caractère marqué au milieu. Si Shift est pressé juste avant eux, ils produisent le caractère marqué en haut.

Dactylographie

Afin de générer un caractère, la dactylo le trouve sur le clavier et vérifie si la touche Maj doit être enfoncée. Si c'est le cas, il essaie d'abord d'appuyer sur une touche Maj et de la maintenir enfoncée. Ensuite, il essaie immédiatement d'appuyer sur la touche cible et relâche toutes les touches Maj . Il relâche la touche Maj strictement après avoir tenté d'appuyer sur la touche cible.

Cependant, en raison de l'ivresse, il manque souvent des clés. Cela sera simulé en choisissant un angle aléatoire (uniformément), en déplaçant l'emplacement de la presse d'une quantité aléatoire (avec une distribution appropriée) dans cette direction et en appuyant sur la touche atterri.

Défi

Vous recevrez en entrée un texte à écrire et un paramètre numérique indiquant le niveau d'ivresse. Vous afficherez le texte tapé par la dactylo ivre, avec des fautes de frappe générées par l'algorithme décrit ci-dessus.

Caractéristiques

  • Le texte saisi ne contiendra que des caractères ASCII imprimables, des tabulations et des retours à la ligne.
  • Le paramètre d'entrée est une sorte de valeur numérique scalaire. Sa portée peut être spécifiée dans la réponse, mais l'augmentation de la valeur devrait augmenter la distance moyenne des échecs et vice versa.
  • Vous pouvez adapter le clavier à n'importe quelle taille interne; les tailles d'unité ci-dessus ne sont que des exemples.
  • Les coordonnées utilisées doivent être précises au millième de la hauteur de clé.
  • Le programme doit produire des résultats différents pour chaque invocation. (Des choses comme srand(time(NULL));, c'est-à-dire changer chaque seconde, sont assez bonnes.)
  • La distribution des distances manquées peut être une distribution normale ou toute autre distribution qui fonctionne de manière similaire (grande probabilité de petites valeurs, diminue rapidement pour des valeurs plus grandes; par exemple, une exponentielle négative serait bien).
  • Le doigt de la dactylo est un point unique. Pas besoin de penser à son rayon.
  • La dactylo peut viser n'importe où à l'intérieur d'une clé, tant qu'elle n'est pas sur le bord. Le centre, la position constante, etc. sont valides.
  • La façon dont vous choisissez les touches Maj peut être n'importe quoi. Un choix constant est autorisé, mais les deux touches Shift doivent fonctionner si une pression Shift manquée se termine là.
  • Shift n'affecte une touche que si elle est maintenue enfoncée (c'est-à-dire que la touche Shift a tenté avant une autre touche et a réussi). Les touches "normales" qui atterrissent sur Shift ne font rien.
  • La touche Maj est pressée juste avant la vraie touche et relâchée rapidement, donc aucune répétition de caractère ne se produit si la mauvaise touche est maintenue enfoncée.

Exemple d'E / S

Tous les exemples ci-dessous proviennent de la solution de référence, qui utilise une distribution normale de la distance et choisit toujours le décalage gauche. Les tabulations sont affichées sous forme d'espaces par SE, mais doivent apparaître dans les sorties réelles.

Entrée: 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.
ivresse: 0.3
sortie: 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.

Entrée: identique à l'
ivresse précédente: 2.0
Sortie: /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

Entrée: ( de Wikipedia ) 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).
Ivresse: 0.5
Sortie: 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).

Solution de référence

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
PurkkaKoodari
la source
En relation.
PurkkaKoodari
1
Que dit le fond?
ericw31415
2
@ ericw31415 Une dactylo rentre chez elle après avoir bu un peu et se rend compte qu'une lettre importante doit encore être écrite. Pour s'assurer qu'il obtient le texte correct, il écrit le texte caractère par caractère pour être sûr du résultat. Cependant, il parvient toujours à manquer certaines des clés. Votre tâche consiste à écrire du code qui simule sa saisie. Afin de minimiser le risque d'erreurs, le code doit être aussi court que possible. (J'espère que je n'ai pas fait de fautes de frappe!)
M. Xcoder
Cela ne semble pas si bon si Ctrl + A insère A... Un doigt peut-il sortir du clavier?
l4m2

Réponses:

1

JavaScript (ES7), 672 octets

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))

Non golfé

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))

darrylyeo
la source
2

Röda , 720 789 octets

{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}

Essayez-le en ligne!

Il peut probablement être joué plus ...

Edit: correction d'un bug (+69 octets)

fergusq
la source
Oh désolé, j'ai regardé le mauvais champ! Oups
M. Xcoder
1

Nettoyer , 1011 ... 842 octets

Beaucoup plus de travail pourrait être fait à ce sujet.

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[]_=[]

Essayez-le en ligne!

Οurous
la source