Найти преступника из его уха, пальца и головы


17

До обнаружения отпечатков пальцев и анализа ДНК британская полиция использовала антропометрическую систему для выявления повторных преступников. Определенные части тел преступников были измерены и сохранены в записях - эти части тела, как предполагалось, не изменились в размере после взрослой жизни. Эта система была известна как bertillonnage .

На диаграмме ниже показана система регистрации, используемая полицией для быстрого доступа к этим записям.

Стол Диаграмма 1: Система подачи с пронумерованными ящиками.
Примечание: если вы не видите изображение, попробуйте зеркало imgur или скомпилируйте его самостоятельно .

Шкаф состоит из 81 пронумерованных ящиков. Каждый ящик содержит карточки, и каждая карточка имеет размеры отдельных частей тела преступника:

  • Длина их головы ( H)
  • Ширина их головы ( B)
  • Ширина их правого уха ( E)
  • Длина их указательного пальца ( F)

Каждое измерение классифицируется как маленькое, среднее или большое.

Например, ящик 56 содержит карты со следующими характеристиками: малая H, B большой, средние Е, и малые F. Это может быть нотировано с помощью букв S, Mи Lв месте малых, среднего и большая:

SH,LB,ME,SF

Обратите внимание, что сначала идет буква размера, а затем измерение. Кроме того, восклицательный знак !может быть помещен впереди, чтобы вызвать отрицательный результат:

!SH,LB,!ME,SF

Это указывает на карты, которые имеют следующие характеристики: не маленький H, большой B, не средний E и маленький F. Есть четыре ящика, которые содержат карты с этими характеристиками - 58, 60, 61 и 63.

Ваша задача - написать программу, которая при наличии строки с указанием некоторых характеристик выводит все ящики, в которых содержатся карточки с этими характеристиками. Если нет выдвижных ящиков с карточками с заданными характеристиками, выведите 0.

Вот несколько примеров входов и выходов.

  1. Вход: SH,LB,ME,SF
    Выход:56
  2. Вход: !SH,LB,!ME,SF
    Выход:58,60,61,63
  3. Вход: SB,!MF,!LF
    Выход:1,2,3,4,5,6,7,8,9
  4. Вход: MH,!MH
    Выход:0

Это код гольф, поэтому выигрывает самый короткий вход. Задайте вопросы в комментариях, если спецификация не ясна.


Как историческая справка о точности, системы bertillonnage были на самом деле намного сложнее, чем эта упрощенная версия, используя 9 измерений вместо 4, и, следовательно, используя более сложную систему регистрации, чем тот, что изображен здесь.
Абсент

4
о нет! не ДРУГОЙ вопрос судоку ;-)
Уровень Река St

1
@steveverrill Я на самом деле сделал диаграмму из шаблона судоку, так что в этом есть доля правды: o
Абсент

Ответы:



6

Рубин 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

Редактировать:

  • применил советы Три если по виски .
  • взяты параметры из командной строки, чтобы сохранить еще несколько символов

Демо онлайн: http://ideone.com/lodTLt


selectэто более короткий синоним для find_all. Вы можете обрезать еще два символа, заменив y[-2..-1]с y[-2,2], и еще три по- прежнему используя ==[]вместо .empty?.
Три If By Whisky

@ThreeIfByWhiskey Отличные советы, спасибо! Я отредактировал свой ответ.
Кристиан Лупаску,

2

Скала - 951

Определенно не выиграю этот, главным образом из-за названий встроенных функций, я думаю.

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

Аргумент передается в функцию f

f("SH,LB,ME,SF") знак равно 56


2

T-SQL - 547 544

Не победная запись, но подходит для такого рода проблем.

Настройка таблицы сетки - 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)

Запрос - 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)

Ввод осуществляется путем объявления @i перед запросом

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

Я мог бы сохранить еще 89 символов, если выходные данные не должны быть разделены запятой

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

Представляет каждый номер ячейки в основании 3. Каждая позиция цифры представляет телесный признак. Значение цифры {0,1,2} представляет «Малый», «Средний», «Большой», соответственно.

Особенности соответствуют цифрам следующим образом:

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

Например, вход,

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

Значит:

«LB» подразумевает ширину OfHead = 2 (большой)

«SF» подразумевает IndexFingerLength = 0 (маленький)

«SH» подразумевает LengthOfHead = 0 (маленький)

«ME» подразумевает WidthOfRightEar = 1 (средний)

2001в базе 3 - 55 в базе 10.

Нам нужно добавить один, потому что мы считаем ячейки от 1, а не от нуля.


Код

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

Тестовые случаи

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 - попробуй!

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

Питон 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]

Вывод имеет квадратные скобки, и его не волнует порядок вывода.
Несколько предложений от Фалько и пара от меня, чтобы снять 10 символов.


Да, это нормально, если ввод заключен в скобки.
Абсент

Они должны быть в порядке?
Bizangles

Хороший вопрос. На самом деле, вывод не должен быть в порядке - хотя я не уверен , как выводить их в другом порядке спасут символы.
абсент

Я использую python set () s, преобразовываю их обратно в списки, получаю продукт, преобразовываю числа в base 3 обратно в целые числа. Во всем этом порядок немного перемешан, и мне нужно использовать sorted (), если я хочу вернуть их в правильном порядке.
Bizangles

Понимаю. Порядок не важен, поэтому сортировка () может быть удалена. Хорошее решение.
Абсент
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.