Gestione dell'inventario di Minecraft


11

La gestione dell'inventario di Minecraft è difficile. Hai 17 diamanti, ma hai bisogno di 7 per creare un tavolo degli incantesimi, un piccone e una spada. Li raccogli e fai clic destro 7 volte? O fai clic destro una volta e fai clic destro due volte e prendi il 7 a sinistra? È così confuso!

per quelli di voi che sono ora confusi, non ti preoccupare, ti spiegherò tutto in un secondo

Sfida

Data la dimensione di una pila di articoli e un importo desiderato, determinare il numero minimo di clic per ottenere tale importo. Devi solo gestire fino a 64 per entrambi gli input e puoi supporre di avere infiniti slot di inventario. Non è possibile utilizzare il trucco trascina per distribuire.

definizioni

L' inventario è una raccolta di slot in cui è possibile memorizzare articoli.

Uno slot è uno spazio di archiviazione nel tuo inventario in cui è possibile posizionare fino a un tipo di articolo.

Una pila è un numero di oggetti posizionati nello stesso gruppo. Ai fini di questa sfida, uno stack è semplicemente un gruppo di oggetti nello stesso posto (quindi ignora le dimensioni dello stack)

Il cursore è il tuo oggetto appuntito. Quel cursore. Può avere elementi "su di esso"; in altri termini, se si fa clic su uno slot e si raccolgono gli oggetti, gli oggetti che hai raccolto sono "sul cursore" fino a quando non li metti giù.

specificazioni

Esistono quattro possibili situazioni. O hai un oggetto sul tuo cursore oppure no, e fai clic con il tasto sinistro o destro.

Se non hai un oggetto sul cursore e fai clic con il pulsante sinistro del mouse su uno slot, raccogli l'intera pila.

Se non hai un oggetto sul cursore e fai clic con il pulsante destro del mouse su uno slot, raccogli metà dello stack, arrotondato per eccesso.

Se hai un elemento sul cursore e fai clic con il pulsante sinistro del mouse su uno slot, inserisci tutti gli elementi nello slot. (Per tutti voi giocatori di Minecraft, non avrete> 64 oggetti per questa sfida e sono tutti impilabili a 64, e avete solo un tipo quindi lo scambio di oggetti non si applica qui)

Se hai un elemento sul cursore e fai clic con il pulsante destro del mouse su uno slot, inserisci un elemento nello slot.

Quindi, inizi con tutti gli elementi dati (primo input o secondo; puoi scegliere l'ordine) in uno slot e vuoi finire con la quantità desiderata (altro input) nel cursore.

Facciamo un esempio. Supponi di iniziare con 17 oggetti e che desideri 7. Innanzitutto, fai clic con il pulsante destro del mouse sulla pila, il che significa che hai raccolto 9 e ce ne sono 8 in quello slot. Quindi, se fai nuovamente clic con il pulsante destro del mouse sullo stack, rimetti un oggetto nello slot, lasciandoti con 8 e lo slot con 9. Infine, fai di nuovo clic con il pulsante destro del mouse e hai 7 e lo slot ha 10. Quindi, restituiresti 3(il numero di clic).

Se riesci a farmi il click-golf, per favore dimmelo e io modificherò l'esempio: P

Casi test

Questi sono generati manualmente, quindi per favore dimmi se ci sono errori. Eseguo la gestione dell'inventario facendo clic con il pulsante destro del mouse, quindi non ho esperienza con la gestione ottimale dell'inventario: P

Given, Desired -> Output
17, 7 -> 3
64, 8 -> 5
63, 8 -> 5
10, 10 -> 1
10, 0 -> 0 # note this case
25, 17 -> 7

spiegazioni

Questa sfida potrebbe essere difficile per i giocatori non Minecraft, non ne ho idea. Ecco alcune spiegazioni.

64, 8 -> 5 perché raccogli 32 usando il tasto destro del mouse, posizionalo verso il basso, raccogli 16, posizionalo verso il basso, quindi raccogli 8.

63, 8 -> 5 per la stessa ragione.

25, 17 -> 7 perché raccogli 13, posizionalo in basso, raccogli 6 dal rimanente 12, rimetti 2 nella pila rimanente, quindi posiziona il 4 nel cursore nel 13, quindi raccogli quelli.

Regole

  • Si applicano scappatoie standard
  • Si può presumere che 0 <= desired <= given <= 64
  • È possibile accettare input in entrambi gli ordini ed eseguire I / O in qualsiasi formato ragionevole



2
Quindi è come uno stato-macchina che inizia con uno stato di 0,[n], può passare: (1) da 0,[a,b,...]a a,[b,...], b,[a,...], ceil(a/2),[floor(a/2),b,...], o ceil(b/2),[a,floor(b/2),...]; o (2) da x,[a,b,...]( x>0) a x-1,[a+1,b,...], x-1,[a,b+1,...], x-1,[a,b,...,1], 0,[a+x,b,...], 0,[a,b+x,...], 0,[a,b,...,x]. La sfida è quindi quella di trovare le transizioni minime possibili da 0,[g]dove g è dato a t,Ldove tè il target desiderato ed Lè un elenco?
Jonathan Allan,

Risposte:


2

C ++ , 498 482 457 byte

Se questa funzione viene chiamata una sola volta, può essere 455 byte.

Ho scoperto che quasi tutti i compilatori GCC online (incluso TIO) mi proibiscono di omettere il tipo di funzione f. Tuttavia, il GCC sul mio computer lo consente e non so perché.

Questo può gestire input di grandi dimensioni se uno slot può contenere quel numero di elementi (sebbene necessiti di un array più grande e probabilmente finirà il tempo).

#import<bits/stdc++.h>
#define t N.first
#define X n.erase(n.find
#define p(c){if(c==r)return l;if(L.emplace(w={n,c},l).second)Q[U++]=w;}
#define T(S,C)n.insert(S);p(C)X(S));
using m=std::multiset<int>;using s=std::pair<m,int>;s Q[99999];int x,l,B,U;int f(int a,int r){if(!r)return 0;std::map<s,int>L;s f({a},B=0),w,N;L[Q[U=1]=f];for(;;){l=L[N=Q[B++]]+1;x=N.second;t.insert(0);for(int i:t){m n=t;X(i));if(x){T(i+x,0)T(i+1,x-1)}if(!x&&i){p(i)T(i/2,i-i/2)}}}}

Ungolfed:

#include <map>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

struct state {
    multiset<int> t; int q;
    bool operator<(const state& i) const { return make_pair(t, q) < make_pair(i.t, i.q); }
};

int f(int a, int target) {
    if (target == 0) return 0;

    map<state, int> len;
    queue<state> qu;
    state first = {{a}, 0};
    qu.push(first);
    len[first] = 0;

    #define push(c) { state a = {n, c}; auto t = len.insert({a, l + 1}); if (t.second) { \
        if (a.q == target) return l + 1; qu.push(a); \
    } } // push new state into queue and check for termination
    #define next(stk, cur) { n.insert(stk); push(cur); n.erase(n.find(stk)); }
    // insert new stack, push new state, erase the stack (for another use)

    while (qu.size()) { // BFS cycle
        state now = qu.front();
        qu.pop();

        int q = now.q;
        int l = len[now];

        multiset<int> n(now.t);
        for (int i : now.t) { // click on non-empty stack
            n.erase(n.find(i));
            if (!q) { // nothing on cursor
                push(i); // click left
                next(i / 2, (i + 1) / 2); // click right
            }
            else { // item on cursor
                next(i + q, 0); // click left
                next(i + 1, q - 1); // click right
            }
            n.insert(i);
        }
        if (q) { // click on empty stack
            next(q, 0); // click left
            next(1, q - 1); // click right
        }
    }
}

1

Gelatina , 74 byte

Ẏċ⁴¬
HĊ,$Ḟµ€1¦€F€;⁸Ḣ,$€
‘1¦€ṭ€⁹’¤
+1¦€⁹ṭ€0;ç
⁹Ȧ‘Ḥ¤ŀ
Ṫ;0ṙJ$çḢ
Wṭ0WÇ€Ẏ$ÑпL’

Un programma completo con il primo input (3 ° argomento) lo stack corrente e il secondo input (4 ° argomento) il cursore desiderato.

Provalo online! A causa dell'implementazione, questo porta al timeout TIO di 60 secondi per il25, 17test case. Questo può essere risolto rimuovendo gli esuberi lasciati per la giocosità usando questo 84 byter (che filtra le pile di dimensioni zero e ordina quelle rimaste conḟ€Ṣ¥0¦€0alla fine del collegamento 6 e mantiene solo stati unici ad ogni passo con l'uso diQ$in Main link).

Come?

Il programma implementa la macchina a stati definita.
Crea lo stato originale, [0, [argument 1]]
quindi passa ripetutamente a tutti i successivi stati possibili
fino a quando non viene trovato uno corrispondente [argument 2, [...]].

Nota: la voce del programma si trova nel "Link principale" che è quello più in basso ( Wṭ0WÇ€Ẏ$ÑпL’)

Ẏċ⁴¬ - Link 1, test a list of states for not having the desired cursor
Ẏ    - tighten by one
  ⁴  - program's fourth argument (second input) - desired cursor
 ċ   - count occurrences (the stack list will never match, so just inspecting the cursors)
   ¬ - logical negation

HĊ,$Ḟµ€1¦€F€;⁸Ḣ,$€ - Link 2, next states given a 0 cursor: list, rotatedStacks; number currentCursor (unused)
     µ€1¦€         - for each rotation of rotatedStacks apply to the first element:
H                  -   halve
   $               -   last two links as a monad
 Ċ                 -     ceiling
  ,                -     pair
    Ḟ              -   floor (vectorises) -- i.e. n -> [floor(ceil(n/2)),floor(n/2)]
                                                     = [ceil(n/2),floor(n/2)]
          F€       - flatten each -- i.e. each [[c1,f1],s2, s3,...] -> [c1,f1,s2,s3,...]
             ⁸     - chain's left argument, rotatedStacks
            ;      - concatenate -- i.e. [[c1,f1,s2,s3,...],[c2,f2,s3,...,s1],...,[s1,s2,s3,...],[s2,s3,...,s1],...]
                $€ - last two links as a monad for each:
              Ḣ    -   head
               ,   -   pair -- i.e. [c1,f1,s2,s3,...] -> [c1,[f1,s2,s3,...]]

‘1¦€ṭ€⁹’¤ - Link 3, next states given a non-0 cursor and a right-click: list, rotatedStacks; number currentCursor
 1¦€      - for each rotation of rotatedStacks apply to the first element:
‘         -   increment -- i.e. place an item into the first stack of each rotation
        ¤ - nilad followed by link(s) as a nilad:
      ⁹   -   chain's right argument -- currentCursor
       ’  -   decrement
    ṭ€    - tack each -- i.e. [s1-1,s2,s2,...] -> [currentCursor-1,[s1-1,s2,s2,...]]

+1¦€⁹ṭ€0;ç - Link 4, next states given a non-0 cursor: list, rotatedStacks; number currentCursor
 1¦€       - for each rotation of rotatedStacks apply to the first element:
    ⁹      -   chain's right argument -- currentCursor
+          -   add
     ṭ€0   - tack each to zero -- i.e. [s1+currentCursor,s2,s3,...] -> [0,[s1+currentCursor,s2,s3,...]]
         ç - call the last link (3) as a dyad -- get the right-click states
        ;  - concatenate

⁹Ȧ‘Ḥ¤ŀ - Link 5, next states: list, rotatedStacks; number currentCursor
     ŀ - call link at the given index as a dyad...
    ¤  -   nilad followed by link(s) as a nilad:
⁹      -     chain's right argument -- currentCursor
 Ȧ     -     any & all -- for our purposes zero if zero, one if not
  ‘    -     increment
   Ḥ   -     double
       - -- i.e. call link 2 if currentCursor is zero else call link 4

Ṫ;0ṙJ$çḢ - Link 6, next states: currentState  e.g. [cc, [s1, s2, s3, ...]]
Ṫ        - tail -- get the stacks, [s1, s2, s3, ...]
 ;0      - concatenate a zero - add an empty stack to the options for use
     $   - last two links as a monad for each:
    J    -   range(length)
   ṙ     -   rotate left by -- i.e. [[s2,s3,0,...,s1],[s3,0,...,s1,s2],[0,...,s1,s2,s3],[...,s1,s2,s3,0],...[s1,s2,s3,0,...]]
       Ḣ - head -- get the currentCursor, cc
      ç  - call the last link (5) as a dyad

Wṭ0WÇ€Ẏ$ÑпL’ - Main link: initialStack, requiredCursor
W             - wrap -- [initialStack]
 ṭ0           - tack to zero -- [0, [initialStack]]
   W          - wrap -- [[0, [initialStack]]]
         п   - loop while, collecting the results:
        Ñ     - ...condition: call next link (1) as a monad -- cursor not found
       $      - ...do: last two links as a monad:
    ǀ        -   call the last link (6) as a monad for each
      Ẏ       -   flatten the resulting list by one level
           L  - length
            ’ - decremented (the collect while loop keeps the input too)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.