Campeonato Nacional de Conflitos de Agendamento


25

xkcd: agendando conflitos

(Eu pretendia postar isso em 1542: o conflito de agendamento ainda era o xkcd atual, mas eu tinha um conflito de agendamento.)

Entrada

A entrada será uma lista de 3nelementos, que representam neventos. O primeiro elemento em cada grupo de 3 será o nome de um evento; o segundo e o terceiro, o horário inicial e final, respectivamente. Por exemplo:

foo 12 34 bar 56 78

representa um evento fooque começa no "horário 12" (os horários são representados simplesmente por números inteiros; você pode pensar neles como minutos depois da meia-noite) e termina às 34, e um segundo evento barque começa às 56 e termina às 78.

Os nomes dos eventos sempre serão compostos apenas por caracteres alfanuméricos e os horários serão sempre números inteiros ≥ 0 e <1440. O horário de término será sempre pelo menos 1 maior que o horário de início. Não é garantido que eles sejam classificados de forma alguma.

Se você preferir, considere isso como uma única string separada por espaço; caso contrário, deve ser tomado como uma matriz, lista, vetor ou equivalente do seu idioma.

Saída

A saída deve ser uma lista separada por espaços de nomes de eventos. As regras para as quais os nomes de eventos serão exibidos:

  • Nenhum dos eventos que você produz pode entrar em conflito entre si. Por exemplo, com a entrada a 0 10 b 5 15, você não pode produzir os dois ae bporque os horários estão em conflito (ou seja, se sobrepõem parcialmente). Se um evento terminar exatamente quando outro iniciar, você poderá incluir os dois.

  • Você não pode exibir o evento chamado NSCC("Competição Nacional de Conflitos de Agendamento"), do qual sempre haverá exatamente um deles na entrada. Você também deve gerar pelo menos um evento em conflito (parcialmente sobreposto) com NSCC(e sempre haverá pelo menos um deles).

  • Você deve gerar o maior número possível de eventos enquanto segue as duas regras acima. (Isso é para que você pareça o mais ocupado possível, para que a falta do NSCC pareça mais credível.)

Isso também pode ser produzido como uma única sequência separada por espaço ou uma matriz, lista, vetor etc.

Pode haver mais de uma saída possível.

Casos de teste

Observe que as saídas listadas são apenas exemplos. Seu código pode gerar algo diferente, desde que siga as três regras acima (principalmente, isso significa que deve haver a mesma quantidade de eventos que o exemplo).

Em: UnderwaterBasketWeavingConvention 50 800 NSCC 500 550
Fora:UnderwaterBasketWeavingConvention

Em: SconeEating 0 50 RegexSubbing 45 110 CodeGolfing 95 105 NSCC 100 200
Fora:SconeEating CodeGolfing

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

Em: NSCC 110 115 A 100 120 B 120 140 C 105 135 D 100 105 E 135 500
Fora:C D E

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

Em: A 10 11 B 11 12 C 12 13 D 13 14 NSCC 15 1090 E 10 16
Fora:E

Sinta-se à vontade para adicionar mais casos de teste em uma edição se houver casos extremos que eu perdi.

Regras

  • Seu código deve ser concluído dentro de 30 segundos para todos os casos de teste fornecidos (isso é mais uma verificação de integridade, pois provavelmente deve ser concluído muito mais rapidamente em todos os casos de teste combinados) em uma máquina pessoal razoável.

  • Isso é , então o código mais curto em bytes vence.


É aceitável usar camelCase para eventos em entradas? por exemplo, usando em underwaterBasketWeavingConvention 50 800 nscc 550vez do seu exemplo?
Fatalize

4
@Fatalize Não sei o que você quer dizer; a entrada é fornecida exatamente como é mostrada. Você deve poder suportar qualquer combinação de caracteres alfanuméricos.
Maçaneta

4
Vou ter que trabalhar em uma solução para isso mais tarde; Estou com um conflito de agendamento no momento.
Alex A.

No segundo exemplo, existem dois espaços entre "CodeGolfing" e "95" - isso é um erro, ou precisamos considerar números arbitrários de espaços na entrada? Por enquanto, vou assumir o primeiro, já que você parece um pouco branda no formato da entrada.
vijrox

@VijayRamamurthy Sim, é. Fixo.
Maçaneta

Respostas:


9

Pitão, 45 bytes

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

Este foi bastante difícil de jogar golfe. Encontradas algumas soluções de 45 bytes, essa provavelmente é a mais exótica, pois usa A(atribuição de pares) e .g(grupo por).

Experimente on-line: demonstração ou equipamento de teste

Explicação

                            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 bytes

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,[]),!.

Breve explicação sobre o que cada predicado faz:

  • z(A,B) verifica se um evento A não entra em conflito com nenhum evento de uma lista de eventos B
  • u(A,B)verifica se todos os eventos de uma lista A não conflitam com nenhum evento de uma lista B (usado para verificar se não há conflitos na lista A chamando u(A,A))
  • y(A,B,C) divide uma lista em uma lista de trigêmeos (para transformar entradas em uma lista de eventos)
  • d(A) imprime os nomes dos eventos em uma lista A
  • l(A,R) avalia a lista mais longa de eventos R contida na lista de listas A
  • v(A,NSCC,C,R) retorna uma lista R contendo todas as listas de eventos em A que não possuem conflito interno e que conflitam com o evento NSCC
  • s(A,B) verdadeiro se B é um subconjunto de A
  • x(A) predicado principal, A é a entrada.

Casos de teste : execute test.no intérprete depois de carregar o código acima com o seguinte adicionado depois:

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]).

Isso me levou muito mais tempo do que eu pensava. Provavelmente isso pode ser jogado significativamente mais. Além disso, você provavelmente poderia usar as várias bibliotecas de programação de restrição existentes para obter soluções mais curtas.

Edit: Obrigado a @Oliphaunt pela idéia de usar em A:B:Cvez de [A,B,C]trigêmeos. Salva 14 bytes.

Edit2: Obrigado novamente a @Oliphaunt por apontar que o predicado `` t / 3` era inútil. Salva 55 bytes

Edit3: Obteve 11 bytes usando gramática de cláusula definitiva nos predicados ye d.


Respostas de amor em Prolog! Agradável.
plocks

Também sou amante de Prolog. Sugestões: 1. Acho que você pode usar, por exemplo, em A/B/Cvez dos [A,B,C]trigêmeos, economizando 10 bytes; 2. Você pode usar em \+vez de not? 3. Você poderia explicar por que precisa do corte final x(A)?
Oliphaunt - restabelece Monica

Volto para você amanhã, do meu laptop. Agora, na cama, com o tablet, o que torna a digitação desajeitada e eu provavelmente deveria dormir de qualquer maneira. :-)
Oliphaunt - reinstala Monica

1
Aqui está uma versão que salva 14 bytes. Eu usei, em :vez de /me beneficiar da associatividade correta do ex, ou seja, para que eu pudesse escrever A:_como uma abreviação de A:_:_(mas A+B/Cfunciona tão bem: você pode usá-lo A+_). A propósito, também no seu original você poderia ter usado em [A|_]vez de [A,_,_]. Note finalmente que minha versão do SWI-Prolog não tinha nth0/4, então usei select/3.
Oliphaunt - reinstala Monica

1
Eu me perguntei antes sobre a necessidade, t(S,T)mas depois esqueci. Agora testado: você pode salvar mais 55 bytes descartando-o totalmente e ligando diretamente s(E,L)de setof/3.
Oliphaunt - restabelece Monica

6

JavaScript ( ES6 ), 228

Segunda tentativa, espero que funcione.

Meu destino é a sequência mais longa de eventos com conflito de tempo, mas sem conflito de tempo quando o evento NSCC é removido. Essa sequência modificada com o NSCC removido é a saída solicitada.

Uso uma pesquisa de largura em primeiro lugar para examinar uma fila de soluções candidatas, começando pela mais longa (a primeira é a lista inicial). A partir de uma solução candidata de n eventos, eu construo e enfilio n mais soluções candidatas, removendo um dos eventos e mantendo os outros.

Uma solução candidata é válida se houver um conflito de tempo 'como está', mas quando o evento NSCC é filtrado, não há conflito. Eu uso uma subfunção K para verificar se há conflitos.

Provavelmente poderia ser jogado um pouco mais ...

Teste a execução do trecho abaixo (sendo EcmaScript 6, apenas 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
Posso perguntar ao ponto de um snippet de pilha se o programa não faz nada se você não chamar a função?
Beta Decay

1
@BetaDecay: o edc65 geralmente adiciona casos de teste que são executados no snippet. Parece que ele voltará a esta resposta em breve, quando suponho que ele adicionará o material que pode ser executado. :)
Alex A.

1
@BetaDecay Estava com pressa. E (pior ainda) falha em um dos testes.
Edc65

1

Java, 828 bytes

Provavelmente existe uma implementação Java mais concisa por aí, mas aqui está minha facada:

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

Declarar todas as variáveis ​​em um só lugar salvará bytes.
Spikatrix

Você não precisa else return.
#

0

Python, 373 caracteres

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]

Cria todas as combinações possíveis e verifica cada uma.

Teste

Entrada: ["NSCC",110,115,"A",100,120,"B",120,140,"C",105,135,"D",100,105,"E",135,500]

Saída:

D
C
E
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.