Trova un criminale dall'orecchio, dal dito e dalla testa


17

Prima della scoperta di impronte digitali e test del DNA, la polizia britannica ha utilizzato un sistema antropometrico per identificare i recidivi. Alcune parti dei corpi dei criminali sono state misurate e archiviate in archivi - si presume che queste parti del corpo non cambino di dimensioni dopo l'età adulta. Questo sistema era noto come bertillonnage .

Lo schema seguente mostra un sistema di archiviazione utilizzato dalla polizia per accedere rapidamente a questi record.

tavolo Schema 1: un sistema di archiviazione con cassetti numerati.
Nota: se non riesci a vedere l'immagine, prova lo specchio imgur o compila da solo .

Il classificatore è composto da 81 cassetti numerati. Ogni cassetto contiene carte e ogni carta ha misure di parti particolari del corpo di un criminale:

  • La lunghezza della loro testa ( H)
  • La larghezza della loro testa ( B)
  • La larghezza dell'orecchio destro ( E)
  • La lunghezza del dito indice ( F)

Ogni misurazione è classificata come piccola, media o grande.

Ad esempio, il cassetto 56 contiene carte con le seguenti caratteristiche: piccolo H, grande B, E medio e piccolo F. Questo può essere notata mediante le lettere S, Me Lin luogo di piccole, medie e grandi dimensioni:

SH,LB,ME,SF

Si noti che la lettera delle dimensioni inizia per prima, quindi quale sia la misurazione. Inoltre, un punto esclamativo !può essere posizionato di fronte per causare un negativo:

!SH,LB,!ME,SF

Questo indica le carte che hanno le seguenti caratteristiche: non piccola H, grande B, non media E e piccola F. Ci sono quattro cassetti che contengono carte con queste caratteristiche: 58, 60, 61 e 63.

Il tuo compito è quello di scrivere un programma che, quando viene data una stringa che noti alcune caratteristiche, produce tutti i cassetti che contengono carte con quelle caratteristiche. Se non ci sono cassetti che contengono carte con le caratteristiche indicate, output 0.

Ecco alcuni input e output di esempio.

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

Questo è il golf del codice, quindi vince l'ingresso più breve. Poni domande nei commenti se le specifiche non sono chiare.


Come nota storica per l'accuratezza, i sistemi di bertillonnage erano in realtà molto più complicati di questa versione semplificata, usando 9 misurazioni invece di 4, e quindi usando un sistema di archiviazione più coinvolto di quello raffigurato qui.
assenzio

4
Oh no! non un'altra domanda del Sudoku ;-)
Level River St

1
@steveverrill In realtà ho realizzato il diagramma da un modello di sudoku, quindi c'è del vero in questo: o
assenzio

Risposte:


1

GolfScript 95 ( DEMO )

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

6

Rubino 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

Modificare:

Demo online: http://ideone.com/lodTLt


selectè un sinonimo più breve di find_all. Puoi tagliare altri due caratteri sostituendoli y[-2..-1]con y[-2,2], e altri tre ancora usando ==[]invece di .empty?.
Three If By Whisky

@ThreeIfByWhiskey Ottimi consigli, grazie! Ho modificato la mia risposta.
Cristian Lupascu,

2

Scala - 951

Sicuramente non vincerò questo, principalmente a causa dei nomi delle funzioni integrate che penso.

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 ","
}

L'argomento viene passato alla funzione f

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


2

T-SQL - 547 544

Non è una voce vincente, ma adatta a questo tipo di problema.

Impostazione tabella griglia - 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)

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

L'input viene effettuato dichiarando @i prima della query

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

Potrei salvare altri 89 caratteri se l'output non deve essere una riga delimitata da virgole

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

1

Mathematica 191 235

Rappresenta ciascun numero di cella nella base 3. Ogni posizione delle cifre rappresenta una funzione corporea. Il valore della cifra, {0,1,2}, rappresenta rispettivamente "Piccolo", "Medio", "Grande".

Le caratteristiche corrispondono alle cifre come segue:

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

Ad esempio, l'input,

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

significa:

"LB" implica breadthOfHead = 2 (grande)

"SF" implica IndexFingerLength = 0 (piccolo)

"SH" implica LengthOfHead = 0 (piccolo)

"ME" implica WidthOfRightEar = 1 (medio)

2001nella base 3 è 55 nella base 10.

Dobbiamo aggiungerne uno perché contiamo le celle da 1, non da zero.


Codice

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

Casi test

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


1

Python 3 - 192 - Provalo!

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)

1

Python 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]

L'output ha parentesi e non importa l'ordine di output
Alcuni suggerimenti da Falko e un paio da me stesso per decollare 10 caratteri.


Sì, va bene avere l'input racchiuso tra parentesi.
assenzio

Devono essere in ordine?
Bizangles,

Buona domanda. In realtà, l'uscita non deve essere in ordine - anche se non sono sicuro di come loro output in un ordine diverso avrebbe salvato caratteri.
assenzio

Sto usando python set () s, riconvertendoli in liste, ottenendo il prodotto, convertendo in 3 numeri di base in ints. In tutto ciò, l'ordine diventa un po 'confuso e ho bisogno di usare sort () se li voglio nell'ordine giusto.
Bizangles,

Vedo. L'ordine non è importante, quindi l'ordinato () può essere rimosso. Bella soluzione.
assenzio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.