Пошук тупика


18

Пошук тупика

Програмуючи багатопотокове додаток, слід уважно ставитися до того, щоб уникнути тупикового забруднення різних потоків під час доступу до спільних ресурсів. Тупиковий відбувається , коли потік намагається отримати доступ до ресурсу , який замкнений в іншому потоці , в той же час, інший потік намагається отримати доступ до ресурсу блокується першим. Це простий випадок, але він може бути складнішим з довшими ланцюжками ресурсів.

Змагання

Вам слід написати програму або функцію, яка може виявити можливу ситуацію з тупиком у списку ресурсів, до яких звертається кожен потік. Це код-гольф, тому найкоротша відповідь у байтах виграє.

Кожна нитка запускається одночасно, але після цього вони можуть працювати в будь-якій комбінації переплетення. Якщо є 2 нитки з 4 -х діях кожного, вона може бути запущена як (де кожне число являє собою дію , що робиться нитки з цим ідентифікатором) 1,1,1,1,2,2,2,2, 2,2,2,2,1,1,1,1, 1,2,1,2,1,2,1,2, 1,1,2,2,2,2,1,1, або будь-який інший можливою комбінацією.

Вхідні дані

Ви отримаєте через STDIN функціональний параметр або найближчу альтернативу список рядків. Кожен рядок буде у форматі +a -b. Кожен з цих рядків представляє блокування ( +) / розблокування ( -) ресурсу потоком. Між кожною ниткою буде ---роздільник. Гарантується, що потік не намагатиметься заблокувати ресурс, який він уже заблокував, і що всі потоки явно розблокують усі заблоковані ресурси перед виходом. Наведемо приклад для демонстрації:

+a    # Lock resource a
+b    # Lock resource b
-a    # Unlock resource a
-b    # Unlock resource b
---   # Thread separator
+b    # Lock resource b
-b    # Unlock resource b

Вихід

Вихід повинен бути помилковим, якщо вхід не містить жодної можливості тупикового зв’язку, і правдивим, якщо він містить можливу ситуацію з тупиком. Наприклад:

  • true
  • false
  • 1
  • 0

всі дійсні результати, але все чітко визначене як truthy / falesy буде прийнято.

Приклади

+a
-a
---
+a
-a

Вихід: false


+a
+b
-b
-a
---
+b
+a
-a
-b

Вихід true

Тупик при спробі придбати b,aвідповідно для потоків1,2


+a
+b
-a
-b
---
+a
+b
-b
-a

Вихід false


+a
+b
-b
-a
---
+b
+c
-c
-b
---
+c
+a
-a
-c

Вихід: true

Тупик у потоках 1,2,3 при спробі придбати b,c,aвідповідно.


http://pastebin.com/vMYRZxtW

Вихід false


http://pastebin.com/V5MVgNgS

Вихід true

Тупик в потоках 1,2,3 при спробі отримати b,d,aвідповідно.


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

Бонус

Оскільки це дуже сумно, коли ви виявляєте тупикові ситуації, коли пишете програму, ви отримаєте бонус у розмірі -8 байт для виводу відповідей :(і відповідно :)як truthy / falesy.


Я просто припускаю це, але було б непогано уточнити, що дії кожного потоку (починаючи з верхньої частини потоку) виконуються паралельно і відповідають одному і тому ж системному часу
Optimizer

1
Дії виконуються одночасно, але час, за який кожну дію виконувати, не можна вважати. Може статися, що нитки насправді запускаються строго одна за одною або повністю переплітаються. Можливо, перша половина потоку 1 запускається, потім нитка 2 виконується повністю, потім нитка 1 запускається другою половиною. І так далі. Я оновив питання, щоб уточнити це.
rorlork

1
Ну гаразд, тож завдання полягає в тому, щоб зрозуміти, що з урахуванням будь-якої можливої ​​комбінації разів проходження потоку, чи можливий глухий кут.
Оптимізатор

Так, вибачте, я не думав, що це може залишити сумніви. Насправді в останньому прикладі це продемонстровано, оскільки нитка 2 не намагається використовувати ресурс dпізніше.
rorlork

1
@rcrmn Ви впевнені, що :)не повинно бути неправдивим і :(правдивим?
Тіїло

Відповіді:


4

Пітон 2 - 227

В основному, переконайтеся, що немає циклів "пріоритету". Наприклад, у другому тесті перша нитка має a(b)пріоритет, а друга нитка має b(a)пріоритет.

Я думав над тим, щоб переписати це в Pyth, оскільки я думаю, що це буде добре працювати з усіма операціями itertools, але для перетворення регулярного вираження знадобиться деяка робота, тому зараз я опублікую це і, можливо, спробую перетворити його та опублікувати іншу відповідь пізніше.

from itertools import*
import re
f=lambda t:any(re.search(r"(.)((.)\3)+\1",''.join(p))for i in product(*[[m.group(1)+m.group(2)for m in re.finditer(r"(\w).*(\w).*\2.*\1",e,16)]for e in t.split('---')])for p in permutations(i))

Це відповідає помилково на pastebin.com/V5MVgNgS
Тайло

@Tyilo Він видає True для мене; як саме ти це працюєш?
KSab

о, це було для мене лише читання одного рядка Як ти повинен це запустити?
Тіїло

@Tyilo Я змінив формат, щоб він був функцією, яка приймає багаторядковий рядок як вхід
KSab

5

Пітон - 586 539 524 501 485 байт - 8 = 477

Рівні відступу:

1: 1 space
2: 1 tab
3: 1 tab + 1 space
4: 2 tabs

-

import sys
V=set()
t=[[[]]]
for r in sys.stdin:
 r=r.strip()
 if'---'==r:t.append([[]])
 else:v=r[1:];V.add(v);l=t[-1][-1];t[-1].append(l+[v]if'+'==r[0]else filter(lambda x:x!=v,l))
s=lambda l:s(l[1:])+map(lambda x:(l[0],x),l[1:])if 1<len(l)else[]
E=reduce(set.union,map(lambda x:set(sum(map(s,x),[])),t),set())
for v in V:
 k=set();q=[v]
 while 0<len(q):
    u=q.pop(0)
    if u in k:continue
    k.add(u)
    for x,y in E:
     if u==x:
        if y in k:print':(';sys.exit()
        else:q.append(y)
print':)'

1
Використовуйте ;для об'єднання ліній, відступних для збереження символів. Аналогічно зробіть свої заяви одним лайнером.
isaacg

@isaacg та туз, спасибі! Я думаю, що я покращив його настільки, наскільки міг, використовуючи ваші поради.
Тіїло

BTW, якщо ви не заперечуєте, щоб передати вхід з файлу (або натиснути Ctrl + D двічі), тоді ви можете зробити це for r in sys.stdinзамістьfor r in sys.stdin.readlines()
user12205

@ace Я не бачу різної поведінки між використанням просто sys.stdinабо sys.stdin.readlines(), тому я змінив це, ще раз дякую.
Тіїло

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