Национальный чемпионат по планированию конфликтов


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 кажется более вероятным.)

Это также может быть выведено либо в виде отдельной строки через пробел, либо в виде массива, списка, вектора и т. Д.

Может быть более одного возможного выхода.

Контрольные примеры

Обратите внимание, что перечисленные результаты являются только примерами. Ваш код может выводить что-то другое, если он все еще следует трем правилам, указанным выше (в частности, это означает, что количество событий должно быть таким же, как в примере).

In: UnderwaterBasketWeavingConvention 50 800 NSCC 500 550
Out:UnderwaterBasketWeavingConvention

In: SconeEating 0 50 RegexSubbing 45 110 CodeGolfing 95 105 NSCC 100 200
Out:SconeEating CodeGolfing

In: VelociraptorHunting 0 300 NerdSniping 200 500 SEChatting 400 700 DoorknobTurning 650 750 NSCC 725 775
Out:NerdSniping DoorknobTurning

In: NSCC 110 115 A 100 120 B 120 140 C 105 135 D 100 105 E 135 500
Out:C D E

In: A 800 900 NSCC 700 1000 B 650 750 C 950 1050 D 655 660 E 660 665 F 1030 1040 G 1040 1060
Out:A D E F G

In: A 10 11 B 11 12 C 12 13 D 13 14 NSCC 15 1090 E 10 16
Out:E

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

правила

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

  • Это , поэтому выигрывает самый короткий код в байтах.


Допустимо ли использовать camelCase для событий на входах? например, используя underwaterBasketWeavingConvention 50 800 nscc 550вместо вашего примера?
Фатализировать

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

4
Я должен буду работать над решением этого позже; У меня сейчас конфликт с расписанием.
Алекс А.

Во втором примере между «CodeGolfing» и «95» есть два пробела - это ошибка, или нам нужно учитывать произвольное количество пробелов во входных данных? Прямо сейчас я собираюсь предположить первое, поскольку вы, кажется, немного снисходительны к формату ввода.
Виджрокс

@VijayRamamurthy Да, это так. Исправлена.
Дверная ручка

Ответы:


9

Pyth, 45 байт

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

Этот был довольно жестким для гольфа. Нашел довольно много 45-байтовых решений, это, вероятно, самое экзотическое, так как он использует A(pair-assign) и .g(group-by).

Попробуйте онлайн: демонстрация или тестовая привязь

объяснение

                            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, содержащий каждый список событий в A, которые не имеют внутреннего конфликта и которые конфликтуют с событием NSCC
  • s(A,B) истина, если B является подмножеством A
  • x(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.


Люблю ответы в прологе! Хороший.
plocks

Я тоже любитель Пролога. Предложения: 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 является запрошенным выводом.

Я использую поиск в ширину, исследуя очередь возможных решений, начиная с самого длинного (первый - начальный список). Из возможного решения из n событий я строю и ставлю в очередь 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

Python, 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.