Gestion d'inventaire Minecraft


11

La gestion des stocks de Minecraft est difficile. Vous avez 17 diamants, mais vous en avez besoin de 7 pour fabriquer une table d'enchantement, une pioche et une épée. Les ramassez-vous et faites-vous un clic droit 7 fois? Ou faites-vous un clic droit une fois et un clic droit deux fois et prenez le 7 à gauche? C'est tellement déroutant!

pour ceux d'entre vous qui sont maintenant confus, ne vous inquiétez pas, je vais tout expliquer dans une seconde

Défi

Compte tenu de la taille d'une pile d'articles et du montant souhaité, déterminez le moins de clics pour obtenir ce montant. Vous avez seulement besoin de gérer jusqu'à 64 pour les deux entrées et vous pouvez supposer que vous avez des emplacements d'inventaire infinis. Vous ne pouvez pas utiliser l'astuce glisser-distribuer.

Définitions

L' inventaire est une collection d'emplacements où vous pouvez stocker des objets.

Un emplacement est un espace de stockage dans votre inventaire où vous pouvez placer jusqu'à un type d'objet.

Une pile est un certain nombre d'éléments placés dans le même groupe. Pour les besoins de ce défi, une pile est simplement un tas d'objets au même endroit (donc ignorez la taille de la pile)

Le curseur est votre truc pointu. Ce curseur. Il peut contenir des éléments "dessus"; en d'autres termes, si vous avez cliqué sur un emplacement et ramassé des objets, les objets que vous avez ramassés sont "sur le curseur" jusqu'à ce que vous les posiez.

Caractéristiques

Il y a quatre situations possibles. Soit vous avez un élément sur votre curseur, soit vous n'en avez pas, et soit vous faites un clic gauche, soit vous faites un clic droit.

Si vous n'avez pas d'objet sur votre curseur et que vous cliquez avec le bouton gauche sur un emplacement, vous récupérez la pile entière.

Si vous n'avez pas d'élément sur votre curseur et que vous cliquez avec le bouton droit sur un emplacement, vous récupérez la moitié de la pile, arrondie vers le haut.

Si vous avez un élément sur votre curseur et que vous faites un clic gauche sur un emplacement, vous placez tous les éléments dans cet emplacement. (Pour tous les joueurs de Minecraft, vous n'aurez pas> 64 objets pour ce défi et ils sont tous 64 empilables, et vous n'avez qu'un seul type, donc l'échange d'objets ne s'applique pas ici)

Si vous avez un élément sur votre curseur et que vous cliquez avec le bouton droit sur un emplacement, vous placez un élément dans cet emplacement.

Ainsi, vous commencez avec tous les éléments donnés (première entrée ou seconde; vous pouvez choisir l'ordre) dans un emplacement, et vous souhaitez terminer avec la quantité souhaitée (autre entrée) dans votre curseur.

Passons en revue un exemple. Disons que vous commencez avec 17 objets et que vous en voulez 7. Tout d'abord, vous cliquez avec le bouton droit sur la pile, ce qui signifie que vous en avez ramassé 9 et qu'il y en a 8 dans cet emplacement. Ensuite, si vous cliquez à nouveau avec le bouton droit sur la pile, vous remettez un élément dans l'emplacement, vous laissant avec 8 et l'emplacement avec 9. Enfin, vous cliquez à nouveau avec le bouton droit et vous avez 7 et l'emplacement a 10. Ainsi, vous reviendriez 3(le nombre de clics).

Si vous parvenez à me cliquer sur un golf, dites-le moi et je modifierai l'exemple: P

Cas de test

Ceux-ci sont générés manuellement, veuillez donc me dire s'il y a des erreurs. Je fais la gestion de l'inventaire par un clic droit sur la gigue, donc je n'ai pas d'expérience avec la gestion optimale de l'inventaire: 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

Explications

Ce défi pourrait être délicat pour les joueurs non-Minecraft, je n'en ai aucune idée. Voici quelques explications.

64, 8 -> 5 parce que vous prenez 32 en utilisant le clic droit, placez-le vers le bas, ramassez 16, placez-le, puis ramassez 8.

63, 8 -> 5 pour la même raison.

25, 17 -> 7 parce que vous ramassez 13, placez-le vers le bas, ramassez 6 dans les 12 restants, placez 2 dans la pile de restes, puis placez le 4 dans le curseur dans le 13, puis ramassez-les.

Règles

  • Des échappatoires standard s'appliquent
  • Vous pouvez supposer que 0 <= desired <= given <= 64
  • Vous pouvez prendre des données dans l'un ou l'autre ordre et effectuer des E / S dans n'importe quel format raisonnable



2
Il est donc comme un état de machine qui commence par un état de 0,[n], peut passer: (1) à partir 0,[a,b,...]de a,[b,...], b,[a,...], ceil(a/2),[floor(a/2),b,...], ou ceil(b/2),[a,floor(b/2),...]; ou (2) à partir de x,[a,b,...]( x>0) à 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]. Le défi consiste alors à trouver les transitions minimales possibles de 0,[g]où g est donné à t,Ltest la cible souhaitée et Ly a-t-il une liste?
Jonathan Allan

Réponses:


2

C ++ , 498 482 457 octets

Si cette fonction n'est appelée qu'une seule fois, elle peut être de 455 octets.

J'ai trouvé que presque tous les compilateurs GCC en ligne (y compris TIO) m'interdisaient d'omettre le type de la fonction f. Cependant, le GCC sur mon ordinateur le permet, et je ne sais pas pourquoi.

Celui-ci peut gérer de grandes entrées si un emplacement peut contenir ce nombre d'éléments (bien qu'il ait besoin d'un plus grand tableau et qu'il manquera probablement de temps).

#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)}}}}

Non golfé:

#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

Gelée , 74 octets

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

Un programme complet avec la première entrée (3e argument) la pile actuelle et la deuxième entrée (4e argument) le curseur souhaité.

Essayez-le en ligne! En raison de la mise en œuvre, cela atteint le délai d'expiration TIO de 60 secondes pour le scénario de25, 17test. Cela peut être résolu en supprimant les redondances laissées pour golfiness à l'aide de ce 84 octets (qui filtre les piles de taille nulle et trie celles qui restentḟ€Ṣ¥0¦€0à la fin du lien 6 et ne conserve que des états uniques à chaque étape avec l'utilisation deQ$dans le principal lien).

Comment?

Le programme implémente la machine à états définie.
Il crée l'état d'origine, [0, [argument 1]]
puis passe à tous les états possibles suivants à plusieurs reprises
jusqu'à ce que l'un soit trouvé correspondant [argument 2, [...]].

Remarque: l'entrée du programme se trouve sur le "lien principal" qui est le plus bas ( 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)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.