Finden Sie einen Verbrecher an Ohr, Finger und Kopf

17

Vor der Entdeckung von Fingerabdrücken und DNA-Tests verwendete die britische Polizei ein anthropometrisches System, um Wiederholungstäter zu identifizieren. Bestimmte Körperteile von Kriminellen wurden vermessen und in Aufzeichnungen gespeichert. Es wurde angenommen, dass sich diese Körperteile nach dem Erwachsenenalter nicht in ihrer Größe verändert haben. Dieses System wurde als Bertillonnage bezeichnet .

Das folgende Diagramm zeigt ein Ablagesystem, mit dem die Polizei schnell auf diese Aufzeichnungen zugreifen kann.

Tabelle Abbildung 1: Ein Ablagesystem mit nummerierten Schubladen.
Hinweis: Wenn Sie das Bild nicht sehen können, versuchen Sie es mit dem Imgur Mirror oder kompilieren Sie es selbst .

Der Aktenschrank besteht aus 81 nummerierten Schubladen. Jede Schublade enthält Karten, und jede Karte enthält Maße für bestimmte Körperteile eines Kriminellen:

  • Die Länge ihres Kopfes ( H)
  • Die Breite ihres Kopfes ( B)
  • Die Breite ihres rechten Ohrs ( E)
  • Die Länge ihres Zeigefingers ( F)

Jede Messung wird als klein, mittel oder groß klassifiziert.

Zum Beispiel enthält Schublade 56 Karten mit den folgenden Eigenschaften: H klein, groß B, mittlere E und F. Dieser kleine notiert werden kann mit den Buchstaben S, M, und Lanstelle von kleinen, mittleren und großen:

SH,LB,ME,SF

Beachten Sie, dass zuerst der Größenbuchstabe und dann das Maß angegeben wird. Zusätzlich kann ein Ausrufezeichen !vorangestellt werden, um ein Negativ hervorzurufen:

!SH,LB,!ME,SF

Dies weist auf Karten mit den folgenden Merkmalen hin: nicht klein H, groß B, nicht mittel E und klein F. Es gibt vier Fächer, die Karten mit diesen Merkmalen enthalten - 58, 60, 61 und 63.

Ihre Aufgabe ist es, ein Programm zu schreiben, das, wenn eine Zeichenfolge mit bestimmten Merkmalen angegeben wird, alle Schubladen ausgibt, die Karten mit diesen Merkmalen enthalten. Wenn es keine Schubladen gibt, die Karten mit den angegebenen Merkmalen enthalten, wird ausgegeben 0.

Hier sind einige Beispiele für Ein- und Ausgänge.

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

Dies ist Codegolf, also gewinnt der kürzeste Eintrag. Stellen Sie Fragen in den Kommentaren, wenn die Spezifikation nicht klar ist.

Absinth
quelle
Aus historischen Gründen waren Bertillonnage-Systeme viel komplizierter als diese vereinfachte Version. Sie verwendeten 9 Messungen anstelle von 4 und damit ein aufwändigeres Dateisystem als der hier abgebildete.
Absinth
4
Ach nein! keine andere Sudoku-Frage ;-)
Level River St
1
@steveverrill Ich habe das Diagramm tatsächlich aus einer Sudoku-Vorlage erstellt. Darin liegt also etwas Wahres: o
Absinth

Antworten:

1

GolfScript 95 ( DEMO )

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

Ruby 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

Bearbeiten:

  • Drei Tipps von If By Whiskey angewendet .
  • Parameter von der Kommandozeile genommen, um weitere Zeichen zu speichern

Online-Demo: http://ideone.com/lodTLt

Cristian Lupascu
quelle
selectist ein kürzeres Synonym für find_all. Sie könnten noch zwei Zeichen trimmen durch Ersetzen y[-2..-1]mit y[-2,2], und drei weitere noch durch den Einsatz ==[]statt .empty?.
Three If By Whiskey
@ThreeIfByWhiskey Tolle Tipps, danke! Ich habe meine Antwort bearbeitet.
Cristian Lupascu
2

Scala - 951

Wird auf keinen Fall gewinnen, hauptsächlich aufgrund der Namen der eingebauten Funktionen, denke ich.

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

Das Argument wird an die Funktion übergeben f

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

Bakerg
quelle
2

T-SQL - 547 544

Kein Gewinner, aber für diese Art von Problem geeignet.

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

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

Die Eingabe erfolgt durch Deklaration von @i vor der Abfrage

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

Ich könnte weitere 89 Zeichen speichern, wenn die Ausgabe keine durch Kommas getrennte Zeile sein muss

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
quelle
1

Mathematica 191 235

Stellt jede Zellennummer in Basis 3 dar. Jede Ziffernposition repräsentiert ein Körpermerkmal. Der Wert der Ziffer {0,1,2} steht für "Klein", "Mittel" bzw. "Groß".

Die Merkmale entsprechen den Ziffern wie folgt:

{"widthofhead", "indexfinger length", "lengthofhead", "widthofightear"}

Zum Beispiel die Eingabe,

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

bedeutet:

"LB" impliziert widthOfHead = 2 (groß)

"SF" impliziert IndexFingerLength = 0 (klein)

"SH" impliziert LengthOfHead = 0 (klein)

"ME" impliziert WidthOfRightEar = 1 (mittel)

2001in der Basis 3 ist 55 in der Basis 10.

Wir müssen eins hinzufügen, da wir Zellen von 1 und nicht von Null zählen.


Code

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

Testfälle

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

DavidC
quelle
1

Python 3 - 192 - Probieren Sie es aus!

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

Output hat eckige Klammern und kümmert sich nicht um die Ausgabereihenfolge.
Einige Vorschläge von Falko und ein paar von mir, 10 Zeichen auszuziehen.

Bizangles
quelle
Ja, es ist in Ordnung, die Eingabe in eckige Klammern zu setzen.
Absinth
Müssen sie in Ordnung sein?
Bizangles
Gute Frage. Eigentlich ist der Ausgang nicht in Ordnung zu sein haben - obwohl ich bin mir nicht sicher , wie sie in einer anderen Reihenfolge ausgibt , würde Zeichen speichern.
Absinth
Ich verwende python set () s, konvertiere sie zurück in Listen, erhalte das Produkt und konvertiere in Basis-3-Zahlen zurück in Ints. In all dem wird die Reihenfolge ein wenig durcheinander und ich muss sortiert () verwenden, wenn ich sie wieder in der richtigen Reihenfolge haben möchte.
Bizangles
Aha. Die Reihenfolge ist nicht wichtig, daher kann das sort () entfernt werden. Gute Lösung.
Absinth