Bantu saya mengisi dompet saya!

9

Beberapa waktu yang lalu saya membeli dompet baru yang dapat menampung 8 kartu (4 di kedua sisi). Namun, saya tampaknya memiliki kartu yang jauh lebih banyak dari itu dan saya harus membuat pilihan kartu mana yang ingin saya bawa. Beberapa kartu yang saya gunakan lebih sering daripada yang lain, tetapi kartu yang saya pilih tidak selalu saya gunakan.

Tantangan

Diberikan setumpuk kartu, kembalikan tata letak dompet saya dengan cara terbaik sesuai preferensi dan batasan saya. Tata letak harus sebagai berikut:

__ __ (row 1)
__ __ (row 2)
__ __ (row 3)
__ __ (row 4)

Saat ini saya memiliki kartu berikut - tumpukan akan selalu terdiri dari pilihan dari ini:

  • 1 kartu identitas ( ID )
  • 1 SIM ( DL )
  • 2 kartu kredit ( CC )
  • 5 kartu debit ( DC )
  • 1 kartu transportasi umum ( PC )
  • 1 kartu akses gym ( GC )
  • 9 kartu keanggotaan dari toko dan gudang acak ( MC )

Saya memiliki beberapa preferensi dan batasan:

  • Kartu diurutkan berdasarkan prioritas: ID, DL, CC, DC, PC, GC, MC
  • Kartu diurutkan berdasarkan frekuensi penggunaan: CC, DC, PC, GC, MC, ID, DL
  • Untuk alasan keamanan, jumlah total kartu debit dan kartu kredit di dompet saya bisa paling banyak 1 lebih banyak daripada jumlah semua kartu lain yang masuk ke dompet saya ( N DC + N CCN ID + N DL + N PC + N GC + N MC +1).
  • Jika ada, kartu identitas dan SIM saya harus selalu masuk baris 1. Ini tidak berarti bahwa kartu lain mungkin tidak menempati tempat di baris 1.
  • Kartu yang paling sering digunakan dari tumpukan harus selalu masuk baris 4.

Aturan

  • Tidak ada 2 kartu yang dapat menempati tempat yang sama.
  • Kartu dengan prioritas lebih tinggi selalu lebih disukai daripada kartu dengan prioritas lebih rendah, kecuali jika pembatasan DC / CC masuk.
  • ID / DL pada baris 1 mengesampingkan aturan frekuensi: jika hanya ID yang diberikan, ia akan masuk pada baris 1 dan baris 4 akan kosong!
  • Pemformatan input dapat dilakukan dengan cara apa pun yang Anda suka, selama urutan tumpukan input dipertahankan. misalnya ID,CC,PC,MC,MC,MC,DLdapat juga diberikan sebagai misalnya 1ID 1CC 1PC 3MC 1DL 0DC 0GCatau ID CC PC MC MC MC DL.
  • Pemformatan output memang memiliki beberapa batasan: semua baris harus dimulai pada baris baru, kolom harus dibatasi dengan beberapa cara. Tempat kosong dapat disajikan sesuka Anda, asalkan tidak mengacaukan tata letak 4x2.

  • Mungkin ada lebih dari satu solusi / pesanan, terserah Anda mana yang Anda berikan sebagai output.

  • Anda dapat mengasumsikan bahwa kartu dengan jenis yang sama akan selalu dikelompokkan pada input.
  • Terlepas dari hal di atas, aturan dan celah standar berlaku.

Bonus

Anda diizinkan untuk menghapus 15% dari bytecount Anda jika Anda juga mengembalikan kartu yang tidak masuk dompet. Cetak "Cocok!" jika tidak ada kartu yang tersisa. Output tambahan ini harus dipisahkan dengan jelas dari tata letak returend.

Contohnya

Memasukkan:

ID, DL, CC, GC, MC

2 kemungkinan keluaran:

ID DL      DL ID
__ __  or  __ MC
MC __      __ __
CC GC      GC CC

optional: It fits!

Memasukkan:

ID, CC, DC, PC, GC, MC, MC, MC, MC, MC

2 kemungkinan keluaran:

ID MC      GC ID
MC MC  or  MC PC
PC GC      MC MC
CC DC      DC CC

optional: e.g. (MC, MC)  or  (2MC)

Memasukkan:

DC, DC, CC, CC, GC, DL

2 kemungkinan keluaran:

DL __      GC DL
__ __  or  DC __
GC DC      __ __
CC CC      CC CC

optional: e.g. (DC)  or  (1DC)

Memasukkan:

CC, DC, DC, DC

2 kemungkinan keluaran:

__ __      __ __
__ __  or  __ __
__ __      __ __
CC __      __ CC

optional: e.g. (DC, DC, DC)  or  (3DC)

Memasukkan:

CC, CC, MC, MC, MC, MC, MC, MC, PC, DC, DC, DC, DC, DC, GC

2 kemungkinan keluaran:

MC MC      MC DC
PC GC  or  DC GC
DC DC      PC MC
CC CC      CC CC

optional: e.g. (DC, DC, DC, MC, MC, MC, MC)  or  (3DC, 4MC)

Memasukkan:

MC, MC, MC, MC, MC, MC, MC

2 kemungkinan keluaran:

__ MC      MC MC
MC MC  or  MC MC
MC MC      MC __
MC MC      MC MC

optional: It fits!

Memasukkan:

ID, CC

2 kemungkinan keluaran:

ID __      __ ID
__ __  or  __ __
__ __      __ __
CC __      CC __

optional: It fits!

Ini adalah , jadi kode terpendek (dalam byte) menang.

slvrbld
sumber

Jawaban:

3

Java 10, 385 384 382 byte

C->{String[]R=new String[8],F={"CC","DC","PC","GC","MC"};int c=C.size(),i=1,s=0;c=c>8?8:c;for(var q:C)if("DCC".contains(q))s++;for(;s>c- --s;c=(c=C.size())>8?8:c)i=C.remove(F[i])?i:0;for(c=0,i=8;i>0&c<5;c++)for(;i>0&C.remove(F[c]);)R[--i]=F[c];if(C.remove("ID"))R[c=0]="ID";if(C.remove("DL"))R[c<1?1:0]="DL";for(i=0;i<8;)System.out.print((R[i]!=null?R[i]:"__")+(i++%2>0?"\n":" "));}

Meskipun itu tidak terlalu sulit, saya dapat melihat mengapa itu tidak dijawab. Terutama aturan tentang " N DC + N CC ≤ N ID + N DL + N PC + N GC + N MC +1 " harganya cukup banyak byte saat ini ..
Dan karena sudah sekitar 2,5 tahun sejak tantangan ini telah diposkan, OP mungkin sudah memiliki dompet lain sekarang juga;;

-1 byte terima kasih kepada @Jakob .

Cobalah online.

Penjelasan:

C->{                       // Method with String-List parameter and String return-type
  String[]R=new String[8], //  String-array of size 8
          F={"CC","DC","PC","GC","MC"};
                           //  Frequency-order String-array
  int c=C.size(),          //  Size of the input-List
      i=1,                 //  Index integer, starting at 1
      s=0;                 //  Count-integer, starting at 0
  c=c>8?8:c;               //  If the size is larger than 8, set it to 8
  for(var q:C)             //  Loop over the cards of the input-List
    if("DCC".contains(q))  //   If the card is a DC or CC:
      s++;                 //    Increase the counter by 1
  for(;s>                  //  Loop as long as the amount of DC/CC is larger 
         c- --s;           //  than the other amount of cards + 1
      c=(c=C.size())>8?8:c)//    Recalculate the size after every iteration
    i=C.remove(F[i])?i:0;  //   If the List still contains a DC, remove it
                           //   Else: remove a CC instead
  for(c=0,                 //  Reset `c` to 0
      i=8;i>0              //  Loop as long as there is still room in the wallet,
      &c<5;                //  and we still have cards left
      c++)                 //    Go to the next card-type after every iteration
    for(;i>0               //   Inner loop as long as there is still room in the wallet,
        &C.remove(F[c]);)  //   and we still have a card of the current type left
      R[i--]=F[c];         //    Put a card of the current type in the wallet
  if(C.remove("ID"))R[c=0]="ID";
                           //  Add the 'ID' card to the first row if present
  if(C.remove("DL"))R[c<1?1:0]="DL";
                           //  Add the 'DL' card to the first row if present
  for(i=0;i<8;)            //  Loop over the wallet
    System.out.print(      //   Print:
      (R[i]!=null?         //    If the current slot contains a card:
        R[i]               //     Append this card
       :                   //    Else:
        "__")              //     Append an empty slot ("__")
      +(i++%2>0?"\n":" "));//    Append the correct delimiter (space or new-line)
  return r;}               //  And finally return the result

Java 10, 390,15 (459 byte - 15% bonus)

C->{String r="",R[]=new String[8],F[]={"CC","DC","PC","GC","MC"},t=r;int c=C.size(),i=1,s=0;for(var q:C)if("DCC".contains(q))s++;for(;s>(c>8?8:c)- --s;c=C.size())if(C.remove(F[i]))t+=F[i]+",";else i=0;for(c=0,i=8;i>0&c<5;c++)for(;i>0&&C.remove(F[c]);)R[--i]=F[c];if(C.remove("ID")){t+=R[0]+",";R[c=0]="ID";};if(C.remove("DL")){t+=R[c=c<1?1:0]+",";R[c]="DL";}for(i=0;i<8;)r+=(R[i]!=null?R[i]:"__")+(i++%2>0?"\n":" ");return r+"\n"+(C.size()>0?t+C:"It fits!");}

Cobalah online.

Kevin Cruijssen
sumber
1
Anda dapat menyimpan satu byte dengan menginisialisasi Fdengan {"CC","DC","PC","GC","MC"}.
Jakob
@ Jakob Ah, tidak menyadari bahwa itu lebih pendek. Terima kasih!
Kevin Cruijssen