Знайдіть злочинця з його вуха, пальця та голови


17

До виявлення відбитків пальців та ДНК-тестування британська поліція використовувала антропометричну систему для виявлення правопорушників. Окремі частини тіл злочинців вимірювались і зберігалися в записах - ці частини тіла передбачалося, що вони не змінюються розмірами після повноліття. Ця система була відома як bertillonnage .

На діаграмі нижче представлена ​​система подачі документів, яка використовується поліцією для швидкого доступу до цих записів.

Таблиця Діаграма 1: Система подачі з пронумерованими ящиками.
Примітка. Якщо ви не бачите зображення, спробуйте дзеркало імгур або скомпілюйте його самостійно .

Шафа для подачі складається з 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
О ні! не ДРУГЕ Судоку питання ;-)
Level River 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

Редагувати:

  • застосовано Three If By Whiskey 's tips.
  • взяті параметри з командного рядка, щоб зберегти ще кілька символів

Демонстрація в Інтернеті: http://ideone.com/lodTLt


select- коротший синонім для find_all. Ви можете обрізати ще два символи, замінивши y[-2..-1]на них y[-2,2], і ще три ще, використовуючи ==[]замість .empty?.
Три, якщо по віскі

@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

Математика 191 235

Представляє кожне число комірок у базі 3. Кожна цифра позиції являє собою тілесну ознаку. Значення цифри {0,1,2} позначає відповідно "Малий", "Середній", "Великий".

Особливості відповідають цифрам наступним чином:

{"widethOfHead", "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, перетворюю їх назад у списки, отримую продукт, перетворюю базові 3 числа назад на ints. При всьому цьому замовлення трохи змішується, і мені потрібно використовувати сортировану (), якщо я хочу їх повернути в потрібному порядку.
Bizangles

Я бачу. Замовлення не важливе, тому сортування () може бути видалено. Приємне рішення.
абсент
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.