Національний чемпіонат з розкладу конфліктів


25

xkcd: Конфлікт планування

(Я мав намір опублікувати це під час 1542: Конфлікт планування все ще був поточним xkcd, але у мене виник конфлікт планування.)

Вхідні дані

Вхідним записом буде список 3nелементів, які представляють nподії. Першим елементом у кожній групі з 3 буде назва події; другий і третій, час початку і закінчення відповідно. Наприклад:

foo 12 34 bar 56 78

являє собою подію, fooяка починається в "час 12" (час представлений просто цілими числами; ви можете вважати їх як хвилини минулої півночі) і закінчується о 34, а друга подія, barяка починається в 56 і закінчується в 78.

Назви подій завжди будуть складатися лише з буквено-цифрових символів, а часи завжди будуть цілими числами ≥ 0 та <1440. Час закінчення завжди буде принаймні на 1 більший, ніж час початку. Їх не гарантують будь-яким чином сортувати.

Якщо ви хочете, ви можете прийняти це як єдиний пробіл, розділений пробілом; інакше його слід сприймати як масив, список, вектор або еквівалент вашої мови.

Вихідні дані

Вихід повинен бути розділеним пробілом списком імен подій. Правила, за якими слід виводити назви подій:

  • Жодна з подій, які ви виводили, не може суперечити один одному. Наприклад, за допомогою введення a 0 10 b 5 15ви не можете виводити і те, aі bтому, що часи конфліктують (тобто частково перетинаються). Якщо подія закінчується точно так, як починається інша, ви можете включити обидва.

  • Ви не можете виводити подію під назвою NSCC("Конкурс національних конфліктів з планування"), з яких у вході завжди буде точно одна. Ви також повинні вивести принаймні одну подію, яка конфліктує (частково перекривається) NSCC(і завжди буде також хоча б одна з них).

  • Ви повинні вивести якомога більше подій, дотримуючись вищевказаних двох правил. (Це так, що ви виглядаєте максимально зайнятими, так що відсутність NSCC здається більш надійною.)

Це також може бути виведено як окремий рядок, розділений пробілом, або масив, список, вектор тощо.

Може бути більше одного можливого виходу.

Тестові справи

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

В: UnderwaterBasketWeavingConvention 50 800 NSCC 500 550
Вихід:UnderwaterBasketWeavingConvention

В: SconeEating 0 50 RegexSubbing 45 110 CodeGolfing 95 105 NSCC 100 200
Вихід:SconeEating CodeGolfing

В: VelociraptorHunting 0 300 NerdSniping 200 500 SEChatting 400 700 DoorknobTurning 650 750 NSCC 725 775
Вихід:NerdSniping DoorknobTurning

В: NSCC 110 115 A 100 120 B 120 140 C 105 135 D 100 105 E 135 500
Вихід:C D E

В: A 800 900 NSCC 700 1000 B 650 750 C 950 1050 D 655 660 E 660 665 F 1030 1040 G 1040 1060
Вихід:A D E F G

В: A 10 11 B 11 12 C 12 13 D 13 14 NSCC 15 1090 E 10 16
Вихід:E

Не соромтеся додавати більше тестових випадків у редагування, якщо є випадки, які я пропустив.

Правила

  • Ваш код повинен заповнитись протягом 30 секунд для всіх наданих тестових випадків (це більше перевірка добросовісності, оскільки, ймовірно, має бути виконана набагато швидше для всіх тестових випадків разом) на розумній персональній машині.

  • Це , тому виграє найкоротший код у байтах.


Чи прийнятно використовувати camelCase для подій у входах? наприклад, використовуючи underwaterBasketWeavingConvention 50 800 nscc 550замість вашого прикладу?
Фаталізувати

4
@Fatalize Не впевнений, що ти маєш на увазі; вхід подається точно так, як показано. Ви повинні мати можливість підтримувати будь-яку комбінацію буквено-цифрових символів.
Дверна ручка

4
Пізніше мені доведеться попрацювати над вирішенням цього питання; Зараз у мене конфлікт планування.
Алекс А.

У другому прикладі є два проміжки між "CodeGolfing" і "95" - це помилка, чи нам потрібно враховувати довільні числа пробілів у введенні? Наразі я збираюся припустити колишнє, оскільки ви здаєтеся трохи поблажливішим до формату введення.
vijrox

@VijayRamamurthy Так, так. Виправлено.
Дверна ручка

Відповіді:


9

Pyth, 45 байт

AGH.gqhk"NSCC"m,hdrFtdcQ3hMef&.{KseMT@KehHtyG

Цей був досить важкий для гольфу. Знайдено досить багато 45-байтних рішень, це, мабуть, найекзотичніше, оскільки воно використовує A(пара-присвоєння) та .g(групування).

Спробуйте в Інтернеті: Демонстрація або Тест-джгут

Пояснення

                            implicit: Q = input list
                      cQ3   split Q into triples
              m             map each triple d to:
               ,              the pair containing
                hd              - d[0] (name)
                  rFtd          - range from start-time to end-time
   .g                       group these tuples k by:
     qhk"NSCC"                k[0] == "NSCC"
AGH                         pair assign to G,H. This assigns all
                            tuples != NSCC to G, and the NSCC one to H

                  yG        generate all subsets of G
                 t          remove the first one (the empty subset)
   f                        filter for subsets T, which satisfy:
         eMT                  get the last item (the range) for all tuples in T
        s                     and combine them (sum)
       K                      assign to K
     .{                       check for uniqueness of K (no overlapping times)
    &                         and
            @KehH             check the intersection of K and H[0][1]
  e                         take the last element (most events)
hM                          get the first item (name) for each event
                            and implicitly print this list

13

SWI-Prolog, 537 524 516 502 447 436 байт

z(A:B:C,[D:E:F|G]):-(A=D;B>=F;E>=C),(G=[];z(A:B:C,G)).
u([A|B],C):-z(A,C),(B=[];u(B,C)).
y([A,B,C|D])-->[A:B:C],(y(D);{_=_}).
d-->[A:_],{write(A),tab(1)},d;{_=_}.
l([H|T],R):-T=[],R=H;length(H,N),l(T,X),length(X,M),(N>M,R=H;R=X).
v([],_,R,R).
v([A|T],Z,B,R):-u(A,A),\+z(Z,A),v(T,Z,[A|B],R);v(T,Z,B,R).
s([E|T],[F|N]):-E=F,(N=[];s(T,N));s(T,[F|N]).
x(A):-y(A,D,[]),K="NSCC":_,select(K,D,E),setof(L,s(E,L),B),v(B,K,[],R),l(R,S),d(S,[]),!.

Коротке пояснення того, що робить кожен присудок:

  • z(A,B) перевіряє, чи подія A не суперечить жодній події списку подій B
  • u(A,B)перевіряє, чи кожна подія списку A не суперечить жодній події списку B (використовується для перевірки відсутності конфліктів у списку A шляхом виклику u(A,A))
  • y(A,B,C) розбиває список на список трійки (для перетворення входів у список подій)
  • d(A) друкує назви подій у списку A
  • l(A,R) оцінює найдовший список подій R, що міститься у списку списків A
  • v(A,NSCC,C,R) повертає список R, що містить кожен перелік подій в А, які не мають внутрішнього конфлікту і конфліктують з подією NSCC
  • s(A,B) вірно, якщо B - це підмножина A
  • x(A) основний предикат, A - вхід.

Тестові випадки : виконати test.в інтерпретаторі після завантаження коду вище із наступним доданим після нього:

test:-
    x(["UnderwaterBasketWeavingConvention",50,800,"NSCC",500,550]),
    nl,
    x(["SconeEating",0,50,"RegexSubbing",45,110,"CodeGolfing",95,105,"NSCC",100,200]),
    nl,
    x(["VelociraptorHunting",0,300,"NerdSniping",200,500,"SEChatting",400,700,"DoorknobTurning",650,750,"NSCC",725,775]),
    nl,
    x(["NSCC",110,115,"A",100,120,"B",120,140,"C",105,135,"D",100,105,"E",135,500]),
    nl,
    x(["A",800,900,"NSCC",700,1000,"B",650,750,"C",950,1050,"D",655,660,"E",660,665,"F",1030,1040,"G",1040,1060]),
    nl,
    x(["A",10,11,"B",11,12,"C",12,13,"D",13,14,"NSCC",15,1090,"E",10,16]).

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

Редагувати: Дякую @Oliphaunt за ідею використання A:B:Cзамість [A,B,C]трійки. Економить 14 байт.

Edit2: Ще раз дякую @Oliphaunt за вказівку, що предикат `` t / 3` був марним. Економить 55 байт

Edit3: набрав 11 байт, використовуючи остаточну граматику пункту на предикати yта d.


Любовні відповіді в Prolog! Хороший.
заговори

Я теж любитель Prolog. Пропозиції: 1. Я думаю, що ви можете використовувати, наприклад, A/B/Cзамість [A,B,C]трійки, економлячи 10 байт; 2. Чи можете ви використовувати \+замість not? 3. Чи можете ви пояснити, для чого потрібен остаточний розріз x(A)?
Оліфант - відновити Моніку

Я повернуся до вас завтра, зі свого ноутбука. Прямо зараз у ліжку з планшетом, який робить незграбним набір тексту, і я, мабуть, повинен спати все одно. :-)
Оліфаунт - відновити Моніку

1
Ось версія, яка зберігає 14 байт. Я використовував :замість того, /щоб отримати користь від правої асоціативності колишнього, тобто я міг написати A:_як скорочення A:_:_(але A+B/Cпрацює так само: ви можете використовувати A+_). До речі, також у оригіналі ви могли використовувати [A|_]замість цього [A,_,_]. Зазначимо, нарешті, що в моїй версії SWI-Prolog не було nth0/4, тому я використовував select/3замість цього.
Оліфант - відновити Моніку

1
Я раніше замислювався про необхідність, t(S,T)але потім забув. Зараз перевірено: ви можете зберегти ще 55 байт, видаливши його цілком і безпосередньо s(E,L)з нього setof/3.
Оліфант - відновити Моніку

6

JavaScript ( ES6 ), 228

Друга спроба, я сподіваюся, що ця працює.

Моя мета - це найдовша послідовність подій, яка має конфлікт у часі, але немає конфлікту в часі, коли подія NSCC видаляється. Ця змінена послідовність із видаленим NSCC є запитом на вихід.

Я використовую Breadth First Search, вивчаючи чергу кандидатських рішень, починаючи з найдовшого (перший - початковий список). З кандидатського рішення п яти подій я будую і запитую n більше варіантів вирішення, видалення одного з подій і тримати інше.

Кандидатське рішення є дійсним, якщо існує конфлікт у часі "як є", але коли подія NSCC відфільтрована, конфлікту немає. Я використовую підфункцію K для перевірки конфліктів.

Можливо, можна було б пограти ще трохи ...

Тест запуску фрагмента нижче (це лише EcmaScript 6, FireFox)

F=l=>(K=>{
  l.map(v=>l.push(l.splice(0,3)));// I'm particularly proud of this trick for grouping in triplets (in pith it's "cQ3")
  for(S=[l.sort((a,b)=>a[1]-b[1])];!K(l=S.shift())|K(m=l.filter(x=>x[0]!='NSCC'));)
    l.map((v,i)=>(S.push(n=[...l]),n.splice(i,1)));
})(l=>l.some(x=>[p>+x[1],p=+x[2]][0],p=0))||m.map(x=>x[0])

// Less golfed and ES5

function Find(l) {
  var n,m;
  var Check = function(l) {
    // check timing conflict comparing start time and end time of previous event (events must be sorted)
    var p = 0 // previous event end time, init to 0
    return l.some( function(x) {
      var err = p > +x[1]; // unary plus convert string to number
      p = +x[2]; // update end time
      return err;
    });  
  };  
  // group initial array in triplets
  // forEach repeats for the initial number of elements in l, even if l becomes shorter
  // so it loops more times than necesary, but it works anymay
  l.forEach(function() { 
    l.push(l.splice(0,3)); // remove first 3 elements and add to back as a triple
  }) 
  l.sort(function(a,b) { return a[1]-b[1]} ); // sort by start time
  var S=[l]; // S is the main queue, start with complete list 
  
  while (l = S.shift(), // current list
         m = l.filter( function(x) { return x[0]!='NSCC'} ), // current list with NSCC removed
         !Check(l)|Check(m)) // loop while list ha no errors or filtered list do have errors
  {
    // build new candidate to check
    l.forEach ( function(v,i) {
      n = l.slice(); // make a copy of l
      n.splice(i,1); // remove ith element
      S.push(n); // put in S
    });  
  }
  // when exiting while, m has the list with NSCC removed
  return m.map( function(x) { return x[0]; }); // keep the event name only
}

// Test

out=(...x)=>O.innerHTML += x + '\n';

test=[
  ['UnderwaterBasketWeavingConvention 50 800 NSCC 500 550','UnderwaterBasketWeavingConvention']
, ['SconeEating 0 50 RegexSubbing 45 110 CodeGolfing  95 105 NSCC 100 200','SconeEating CodeGolfing']
, ['VelociraptorHunting 0 300 NerdSniping 200 500 SEChatting 400 700 DoorknobTurning 650 750 NSCC 725 775'
  ,'NerdSniping DoorknobTurning']
, ['NSCC 110 115 A 100 120 B 120 140 C 105 135 D 100 105 E 135 500','C D E']
, ['A 800 900 NSCC 700 1000 B 650 750 C 950 1050 D 655 660 E 660 665 F 1030 1040 G 1040 1060','A D E F G']
, ['A 10 11 B 11 12 C 12 13 D 13 14 NSCC 15 1090 E 10 16','E']
]


test.forEach(x=>{
  var l=x[0].split(/\s+/), r=F(l).sort().join(' '), e=x[1].split(/\s+/).sort().join(' ');
  out('Test ' + (r==e ? 'OK':'FAIL')+'\nInput:    '+x[0]+'\nResult:   '+r+'\nExpected: '+e)
} )
<pre id=O></pre>


3
Чи можу я запитати точку фрагмента стека, якщо програма нічого не робить, якщо ви не зателефонуєте у функцію?
Бета-розпад

1
@BetaDecay: edc65 зазвичай додає тестові випадки, які працюють у фрагменті. Здається, він незабаром повернеться до цієї відповіді, і тоді я припускаю, що він додасть речі, які можна виконати. :)
Алекс А.

1
@BetaDecay поспішав. І (що ще гірше), це не виходить з одного тесту.
edc65

1

Java, 828 байт

Напевно, там є більш стисла реалізація Java, але ось мій удар:

String s(String e){String[] a=e.split(" ");String m="";String[] c=g(a.length/3);int l=0;for(int i=0;i<a.length;i+=3)if(a[i].equals("NSCC"))l=i/3;for(String p:c)if(p.indexOf(l+"")==-1&&!h(p,a)&&h(p+l,a)&&p.length()>m.length())m=p;String r="";for(int i=0;i<m.length();i++)r+=a[3*(m.charAt(i)-48)]+((i==m.length()-1)?"":" ");return r;}boolean h(String c, String[] e){for(int i=0;i<c.length()-1;i++){int p=c.charAt(i)-48;for(int j=i+1;j<c.length();j++){int q=c.charAt(j)-48;if((Integer.parseInt(e[3*p+1])-Integer.parseInt(e[3*q+2]))*((Integer.parseInt(e[3*p+2])-Integer.parseInt(e[3*q+1])))<0)return true;}}return false;}String[] g(int n){if(n>1){String[] result=new String[(int)Math.pow(2,n)];String[] l=g(n-1);for(int i=0;i<l.length;i++){result[2*i]=l[i];result[2*i+1]=l[i]+(n-1);}return result;}else return new String[]{"","0"};}

Оголошення всіх змінних в одному місці дозволить зберегти байти.
Spikatrix

Вам не потрібно else return.
lirtosiast

0

Пітон, 373 символи

import itertools as j
a=zip(*[iter(input())]*3)
f,g,r=[],0,"NSCC"
p=f
for q in a:
 p=(p,q)[q[0]==r]
for h in range(1,len(a)+1):
 for i in j.combinations(a,h):
  s,i,l,m=0,sorted(i,key=lambda k:int(k[1])),-1,len(i)
  for n in i:
   s=(s,1)[p[1]<n[2]or p[2]<n[1]]
   if r==n[0]or n[1]<l:
    m=-1
    break
   else:
    l=n[2]
  if s*m>g:
   g,f=m,i
for o in f:
 print o[0]

Створює всі можливі комбінації та перевіряє кожну.

Тест

Вхід: ["NSCC",110,115,"A",100,120,"B",120,140,"C",105,135,"D",100,105,"E",135,500]

Вихід:

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