Encuentra un criminal de su oreja, dedo y cabeza

17

Antes del descubrimiento de las huellas digitales y las pruebas de ADN, la policía británica utilizó un sistema antropométrico para identificar a los delincuentes reincidentes. Ciertas partes de los cuerpos de los delincuentes se midieron y almacenaron en registros; se supuso que estas partes del cuerpo no cambiarían de tamaño después de la edad adulta. Este sistema se conocía como bertillonnage .

El siguiente diagrama muestra un sistema de archivo utilizado por la policía para acceder a estos registros rápidamente.

Mesa Diagrama 1: Un sistema de archivo con cajones numerados.
Nota: si no puede ver la imagen, pruebe el espejo imgur o compílelo usted mismo .

El archivador consta de 81 cajones numerados. Cada cajón contiene cartas, y cada carta tiene medidas de partes particulares del cuerpo de un criminal:

  • La longitud de su cabeza ( H)
  • La anchura de su cabeza ( B)
  • El ancho de su oreja derecha ( E)
  • La longitud de su dedo índice ( F)

Cada medida se clasifica como pequeña, mediana o grande.

Por ejemplo, el cajón 56 contiene tarjetas con las siguientes características: pequeña H, B grandes, medio E, y pequeña F. Esto se puede notated usando las letras S, My Len lugar de pequeñas, medianas y grandes:

SH,LB,ME,SF

Tenga en cuenta que la letra de tamaño va primero, luego cuál es la medida. Además, !se puede colocar un signo de exclamación delante para causar un negativo:

!SH,LB,!ME,SF

Esto indica cartas que tienen las siguientes características: no pequeña H, grande B, no mediana E y pequeña F. Hay cuatro cajones que contienen cartas con estas características: 58, 60, 61 y 63.

Su tarea es escribir un programa que, cuando se le da una cadena que anota algunas características, genera todos los cajones que contienen tarjetas con esas características. Si no hay cajones que contengan cartas con las características dadas, salida 0.

Aquí hay algunas entradas y salidas de muestra.

  1. Entrada: SH,LB,ME,SF
    Salida:56
  2. Entrada: !SH,LB,!ME,SF
    Salida:58,60,61,63
  3. Entrada: SB,!MF,!LF
    Salida:1,2,3,4,5,6,7,8,9
  4. Entrada: MH,!MH
    Salida:0

Este es el código de golf, por lo que gana la entrada más corta. Haga preguntas en los comentarios si la especificación no es clara.

Ajenjo
fuente
Como nota histórica de precisión, los sistemas de bertillonnage eran en realidad mucho más complicados que esta versión simplificada, utilizando 9 mediciones en lugar de 4, y por lo tanto utilizando un sistema de archivo más complicado que el que se muestra aquí.
ajenjo
44
¡Oh no! no es OTRA pregunta de Sudoku ;-)
Level River St
1
@steveverrill Realmente hice el diagrama a partir de una plantilla de sudoku, así que hay algo de verdad en eso: o
ajenjo

Respuestas:

1

GolfScript 95 ( DEMO )

','/:r;81,{r{1$[[.9%3/\.3%\.27/\9/3%]{'SML'=}%'HEBF']zip{''+}%\.,3=\1${(;}*@?)!!=},!\;},{)}%0or
Cristian Lupascu
fuente
6

Rubí 1.9.3 - 173 157 143

x=(1..81).select{|j|$*[0].split(?,).all?{|y|i=j-1
z='SML'
[z[i%9/3]+?H,z[i%3]+?E,z[i/27]+?B,z[i/9%3]+?F].member?(y[-2,2])^y[?!]}}
p x==[]?[0]:x

Editar:

  • aplicó las puntas de Three If By Whiskey .
  • parámetros tomados de la línea de comando para guardar más caracteres

Demostración en línea: http://ideone.com/lodTLt

Cristian Lupascu
fuente
selectes un sinónimo más corto para find_all. Puede recortar otros dos caracteres reemplazándolos y[-2..-1]con y[-2,2], y tres más aún utilizando en ==[]lugar de .empty?.
Three If By Whisky
@ThreeIfByWhiskey Grandes consejos, gracias! He editado mi respuesta.
Cristian Lupascu
2

Scala - 951

Definitivamente no ganará este, principalmente debido a los nombres de las funciones integradas, creo.

def m(a: List[Int]) = 0 to 8 flatMap (x => a map (_ + 9*x)) toSet
var SH = m(List(1,2,3))
var MH = m(List(4,5,6))
var LH = m(List(7,8,9))
var SE = m(List(1,4,7))
var ME = m(List(2,5,8))
var LE = m(List(3,6,9))
var SB = 1 to 27 toSet
var MB = 28 to 54 toSet
var LB = 55 to 81 toSet
def l(a: List[Int]) = 0 to 2 flatMap (x => a map (_+27*x)) toSet
var SF = l(1 to 9 toList)
var MF = l(10 to 18 toList)
var LF = l(19 to 27 toList)

var j = Map(("LH",LH),("MH",MH),("SH",SH),("LB",LB),("MB",MB),("SB",SB),("LF",LF),("MF",MF),("SF",SF),("LE",LE),("ME",ME),("SE",SE))

def f(x : String) = {
  def h(i : List[String], k : Set[Int]) : Set[Int] = {
      if(i isEmpty) k
      else if(i.head.startsWith("!")) h(i.tail, k filterNot (j(i.head.replace("!","")) contains _))
      else h(i.tail, k intersect j(i.head))
  }
  h(x split "," toList, 1 to 81 toSet) mkString ","
}

El argumento pasa a la función. f

f("SH,LB,ME,SF") = 56

Bakerg
fuente
2

T-SQL - 547 544

No es una entrada ganadora, pero es adecuada para este tipo de problema.

Configuración de tabla de cuadrícula - 254

SELECT ROW_NUMBER()OVER(ORDER BY (SELECT $))I,LEFT(Z,1)E,RIGHT(Z,1)H,LEFT(Y,1)F,RIGHT(Y,1)B INTO G FROM(VALUES('SS'),('MS'),('LS'),('SM'),('MM'),('LM'),('SL'),('ML'),('LL'))FB(Y),(VALUES('SS'),('MS'),('LS'),('SM'),('MM'),('LM'),('SL'),('ML'),('LL'))EH(Z)

Consulta - 293 290

DECLARE @S CHAR(400)='SELECT ISNULL(SUBSTRING(O,2,99),0)FROM (SELECT CONCAT('','',I)FROM G WHERE '+REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REVERSE(@i),',',' AND '),'S!','!S'),'M!','!M'),'L!','!L'),'S','=''S'''),'M','=''M'''),'L','=''L''')+' FOR XML PATH(''''))O(O)';EXEC(@S)

La entrada se realiza declarando @i antes de la consulta

DECLARE @I VARCHAR(50) = 'SB,!MF,!LF';

Podría guardar otros 89 caracteres si la salida no tiene que ser una fila delimitada por comas

DECLARE @S CHAR(400)='SELECT I FROM G WHERE '+REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REVERSE(@i),',',' AND '),'S!','!S'),'M!','!M'),'L!','!L'),'S','=''S'''),'M','=''M'''),'L','=''L''')
MickyT
fuente
1

Mathematica 191 235

Representa cada número de celda en la base 3. Cada posición de dígito representa una característica corporal. El valor del dígito, {0,1,2}, representa "Pequeño", "Medio", "Grande", respectivamente.

Las características corresponden a los dígitos de la siguiente manera:

{"breadthOfHead", "IndexFingerLength", "LengthOfHead", "WidthOfRightEar"}

Por ejemplo, la entrada,

{"SH","LB","ME","SF"}

significa:

"LB" implica breadthOfHead = 2 (grande)

"SF" implica IndexFingerLength = 0 (pequeño)

"SH" implica LengthOfHead = 0 (pequeño)

"ME" implica WidthOfRightEar = 1 (medio)

2001en la base 3 es 55 en la base 10.

Necesitamos agregar uno porque estamos contando celdas desde 1, no desde cero.


Código

c=Characters;t=Table[IntegerDigits[k,3,4],{k,0,80}];
f@i_:=1+FromDigits[#,3]&/@Intersection@@(Cases[t,#]&/@(ReplacePart[{_,_,_,_},{#}]&/@(c/@i
/.Thread[c@"BFHESML"-> {1,2,3,4,0,1,2}]/.{{"!",v_,n_}:> (n-> Except[v]),{v_Integer,n_}:> n-> v})))
/.{}:>0

Casos de prueba

f[{"SH","LB","ME","SF"}]

{56}


f[{"!SH","LB","!ME","SF"}]

{58, 60, 61, 63}


f[{"SB","!MF","!LF"}]

{1, 2, 3, 4, 5, 6, 7, 8, 9}


f[{"MH","!MH"}]

0 0

DavidC
fuente
1

Python 3 - 192 - ¡ Pruébalo!

from itertools import*
S=input().split(',')
print([i+1for i in range(81)if eval('*'.join('(list(product(*["SML"]*4))[i][%d]%s="%s")'%('BFHE'.find(s[-1]),'!='[s[0]>'!'],s[-2])for s in S))]or 0)
Falko
fuente
1

Pitón 2 - 194

from itertools import*
n=map(set,['012']*4)
for x in raw_input().split(','):n['BFHE'.find(x[-1])]&=set(`'SML'.find(x[-2])`)^set('012'*(x<'"'))
print[1+int(''.join(x),3)for x in product(*n)]or[0]

La salida tiene paréntesis, y no me importa el orden de salida.
Algunas sugerencias de Falko y un par de mí para sacar 10 caracteres.

Bizangles
fuente
Sí, está bien tener la entrada entre paréntesis.
absenta
¿Necesitan estar en orden?
Bizangles
Buena pregunta. En realidad, la salida no tiene que estar en orden - aunque no estoy seguro de cómo dar salida en un orden diferente que ahorraría caracteres.
absenta
Estoy usando python set () s, convirtiéndolos de nuevo en listas, obteniendo el producto, convirtiendo a números de base 3 de nuevo a ints. En todo eso, el orden se confunde un poco y necesito usar sorted () si quiero que vuelvan en el orden correcto.
Bizangles
Veo. El orden no es importante, por lo que se puede eliminar el ordenado (). Buena solución
ajenjo