El mecanógrafo borracho

31

Fondo

Un mecanógrafo llega a casa después de beber un poco y se da cuenta de que una carta de importación todavía debe escribirse. Para asegurarse de que examina el texto correctamente, escribe el carácter del texto por el carácter para asegurarse de lo que resulta. Sin embargo, se las arregla para perder algunas de las teclas.

Su tarea es escribir cose que simule su ttping. Para minimizar la posibilidad de errores, el código debe ser tan corto como sea posible.

Teclado

El teclado es un teclado ANSI estándar. En la imagen de abajo, el texto rojo muestra el ancho de la clave. Todas las filas tienen 1 unidad de altura y las teclas sin marcar tienen 1 unidad de ancho.

Teclado de referencia

Las teclas realizan las siguientes acciones (lista solo para evitar confusiones):

  • Shift no hace nada por sí solo, pero si se presiona justo antes de una tecla normal, cambia el resultado.
  • CapsLock alterna el bloqueo de mayúsculas. Si el bloqueo de mayúsculas está activado, las teclas de letras emiten las letras mayúsculas inversas.
  • Retroceso elimina el último carácter de salida, si lo hay.
  • Tabulador , Retorno y Espacio insertan un carácter tabulador, una nueva línea y un espacio, respectivamente.
  • Ctrl , Alt son solo para presentación. Ellos (y faltando el teclado por completo) no hacen nada.
  • Todas las teclas de letras producen la letra minúscula marcada. Si se presiona Shift justo antes de ellos, producen la letra mayúscula. El bloqueo de mayúsculas invierte el caso.
  • Todas las demás teclas producen el carácter marcado en el medio. Si se presiona Shift justo antes de ellos, producen el personaje marcado en la parte superior.

Mecanografía

Para generar un carácter, el mecanógrafo lo encuentra en el teclado y comprueba si es necesario presionar la tecla Shift . Si es así, primero intenta presionar y mantener presionada una tecla Shift . Luego, inmediatamente trata de presionar la tecla objetivo y suelta cualquier tecla Shift . Libera la tecla Mayús estrictamente después de intentar presionar la tecla de destino.

Sin embargo, debido a la embriaguez, a menudo pierde las llaves. Esto se simulará seleccionando un ángulo aleatorio (uniformemente), moviendo la ubicación de la prensa una cantidad aleatoria (con una distribución adecuada) en esa dirección, y presionando la tecla aterrizada.

Reto

Recibirá como entradas un texto para escribir y un parámetro numérico que indica el nivel de embriaguez. Saldrá el texto escrito por el mecanógrafo borracho, con errores tipográficos generados por el algoritmo descrito anteriormente.

Presupuesto

  • El texto de entrada solo contendrá ASCII imprimible, pestañas y líneas nuevas.
  • El parámetro de entrada es algún tipo de valor numérico escalar. Su rango se puede especificar en la respuesta, pero aumentar el valor debería aumentar la distancia de falla promedio y viceversa.
  • Puede escalar el teclado a cualquier tamaño interno; los tamaños de unidad anteriores son solo ejemplos.
  • Las coordenadas utilizadas deben tener una precisión de una milésima de la altura de la clave.
  • El programa debe producir resultados diferentes para cada invocación. (Cosas como srand(time(NULL));, es decir, cambiar cada segundo, son lo suficientemente buenas).
  • La distribución de las distancias perdidas puede ser una distribución normal o cualquier otra distribución que funcione de manera similar (gran probabilidad de valores pequeños, disminuye rápidamente para valores más grandes; por ejemplo, exponencial negativo estaría bien).
  • El dedo del mecanógrafo es un solo punto. No es necesario pensar en su radio.
  • El mecanógrafo puede apuntar a cualquier parte dentro de una tecla, siempre que no esté en el borde. Centro, posición constante, etc. son válidos.
  • La forma de elegir las teclas Shift puede ser cualquier cosa. Se permite la elección constante, pero ambas teclas Shift deben funcionar si una pulsación Shift perdida termina allí.
  • La tecla Mayús solo afecta a una tecla si se mantiene presionada (es decir, la tecla Mayús presionó antes que otra tecla y tuvo éxito). Las pulsaciones de teclas "normales" que aterrizan en Shift no hacen nada.
  • La tecla Shift se presiona justo antes de la tecla real y se suelta rápidamente, por lo que no se repite el carácter si se mantiene presionada la tecla incorrecta.

Ejemplo de E / S

Todos los ejemplos a continuación son de la solución de referencia, que utiliza una distribución normal para la distancia y siempre elige el Shift izquierdo. SE muestran las pestañas como espacios, pero deberían aparecer en las salidas reales.

Entrada: 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.
Borrachera: 0.3
Salida: 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.

Entrada: igual que arriba
Borrachera: 2.0
Salida: /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

Entrada: ( 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).
Borrachera: 0.5
Salida: 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).

Solución de referencia

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
fuente
Relacionado.
PurkkaKoodari
1
¿Qué dice el fondo?
ericw31415
2
@ ericw31415 Un mecanógrafo regresa a casa después de beber un poco y se da cuenta de que todavía hay que escribir una carta importante. Para asegurarse de que obtiene el texto correcto, escribe el texto carácter por carácter para asegurarse del resultado. Sin embargo, todavía se las arregla para perder algunas de las llaves. Su tarea es escribir código que simule su escritura. Para minimizar la posibilidad de errores, el código debe ser lo más breve posible. (¡Espero no haber hecho ningún error tipográfico!)
Sr. Xcoder
Parece que no es tan bueno si Ctrl + A se inserta A... ¿Puede un dedo salir del teclado?
l4m2

Respuestas:

1

JavaScript (ES7), 672 bytes

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

Sin 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
fuente
2

Röda , 720 789 bytes

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

Pruébalo en línea!

Probablemente se pueda jugar más al golf ...

Editar: reparó un error (+69 bytes)

fergusq
fuente
¡Oh, perdón, miré el campo equivocado! Oops
Mr. Xcoder
1

Limpio , 1011 ... 842 bytes

Se podría hacer mucho más trabajo en esto.

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

Pruébalo en línea!

Οurous
fuente