Znajdź przestępcę na podstawie jego ucha, palca i głowy

17

Przed odkryciem odcisków palców i testami DNA brytyjska policja stosowała system antropometryczny do identyfikacji powtarzających się przestępców. Niektóre części ciała przestępców zostały zmierzone i zapisane w rejestrach - założono, że te części ciała nie zmieniają się po dorosłości. Ten system był znany jako bertillonnage .

Poniższy schemat pokazuje system archiwizacji używany przez policję w celu szybkiego dostępu do tych rejestrów.

Stół Schemat 1: System segregowania z numerowanymi szufladami.
Uwaga: jeśli nie widzisz obrazu, wypróbuj lustro imgur lub skompiluj go samodzielnie .

Szafka składa się z 81 ponumerowanych szuflad. Każda szuflada zawiera karty, a każda karta ma wymiary poszczególnych części ciała przestępcy:

  • Długość ich głowy ( H)
  • Szerokość ich głowy (B )
  • Szerokość ich prawego ucha (E )
  • Długość ich palca wskazującego ( F)

Każdy pomiar jest klasyfikowany jako mały, średni lub duży.

Na przykład, szuflada 56 zawiera karty z następujących cech: mała H, duże B, podłoża E i F. Ta mała można zapisaną pomocą liter S, Mlub Lw miejsce, małe, średnie i duże:

SH,LB,ME,SF

Zwróć uwagę, że najpierw jest litera rozmiaru, a następnie jaki jest pomiar. Ponadto wykrzyknik !można umieścić z przodu, aby spowodować negatywne:

!SH,LB,!ME,SF

Wskazuje to na karty, które mają następujące cechy: niezbyt małe H, duże B, nie średnie E i małe F. Istnieją cztery szuflady, które zawierają karty o tych cechach - 58, 60, 61 i 63.

Twoim zadaniem jest napisanie programu, który, gdy otrzyma ciąg znaków z pewnymi cechami, wyprowadzi wszystkie szuflady zawierające karty o tych właściwościach. Jeśli nie ma szuflad zawierających karty o podanej charakterystyce, wyjdź 0.

Oto kilka przykładowych danych wejściowych i wyjściowych.

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

To jest golf golfowy, więc wygrywa najkrótszy wpis. Zadawaj pytania w komentarzach, jeśli specyfikacja nie jest jasna.

Absynt
źródło
Jako historyczną uwagę na dokładność, systemy Bertillonnage były w rzeczywistości znacznie bardziej skomplikowane niż ta uproszczona wersja, wykorzystując 9 pomiarów zamiast 4, a tym samym wykorzystując bardziej zaangażowany system archiwizacji niż ten przedstawiony tutaj.
absynt
4
O nie! nie KOLEJNE pytanie Sudoku ;-)
Level River St
1
@steveverrill Zrobiłem diagram z szablonu sudoku, więc jest w tym trochę prawdy: o
absynt

Odpowiedzi:

1

GolfScript 95 ( DEMO )

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

Rubin 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

Edytować:

  • zastosował Three If By Whisky wskazówki .
  • wziął parametry z wiersza poleceń, aby zapisać więcej znaków

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

Cristian Lupascu
źródło
selectjest krótszym synonimem find_all. Możesz przyciąć kolejne dwie postacie, zastępując y[-2..-1]je y[-2,2], a trzy kolejne nadal, używając ==[]zamiast .empty?.
Three If By Whisky
@ThreeIfByWhiskey Świetne wskazówki, dzięki! Zredagowałem swoją odpowiedź.
Cristian Lupascu,
2

Scala - 951

Zdecydowanie nie wygra tego, głównie ze względu na nazwy wbudowanych funkcji.

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

Argument jest przekazywany do funkcji f

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

bakerg
źródło
2

T-SQL - 547 544

Nie jest to zwycięski wpis, ale pasuje do tego rodzaju problemu.

Konfiguracja tabeli siatki - 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)

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

Wprowadzanie odbywa się poprzez zadeklarowanie @i przed zapytaniem

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

Mógłbym zapisać kolejne 89 znaków, jeśli wynik nie musi być wierszem rozdzielanym przecinkami

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
źródło
1

Matematyka 191 235

Reprezentuje każdy numer komórki w bazie 3. Każda pozycja cyfry reprezentuje funkcję cielesną. Wartość cyfry {0,1,2} reprezentuje odpowiednio „Mały”, „Średni”, „Duży”.

Funkcje odpowiadają cyfrom w następujący sposób:

{„breadthOfHead”, „IndexFingerLength”, „LengthOfHead”, „WidthOfRightEar”}

Na przykład dane wejściowe

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

oznacza:

„LB” implikuje szerokośćOfHead = 2 (duża)

„SF” oznacza IndexFingerLength = 0 (mały)

„SH” oznacza LengthOfHead = 0 (mały)

„ME” oznacza WidthOfRightEar = 1 (średni)

2001w bazie 3 jest 55 w bazie 10.

Musimy dodać jeden, ponieważ liczymy komórki od 1, a nie od zera.


Kod

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

Przypadki testowe

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
źródło
1

Python 3 - 192 - Wypróbuj!

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
źródło
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]

Dane wyjściowe mają nawiasy klamrowe i nie dbają o kolejność produkcji.
Niektóre sugestie Falko i kilka ode mnie, aby zdjąć 10 znaków.

Biżuteria
źródło
Tak, można owinąć dane wejściowe w nawiasy.
absynt
Czy muszą być w porządku?
Bizangles
Dobre pytanie. Faktycznie, wyjście nie musi być w porządku - chociaż nie jestem pewien, jak wyprowadzanie ich w innej kolejności uratuje znaki.
absynt
Korzystam z zestawów python set (s), konwertując je z powrotem na listy, uzyskując produkt, konwertując 3 podstawowe liczby z powrotem na int. Podsumowując, kolejność jest trochę pomieszana i muszę użyć sorted (), jeśli chcę, aby były z powrotem w odpowiedniej kolejności.
Bizangles
Widzę. Kolejność nie jest ważna, więc sorted () może zostać usunięty. Niezłe rozwiązanie.
absynt