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.