Minecraft Inventory Management

11

O gerenciamento de inventário do Minecraft é difícil. Você tem 17 diamantes, mas precisa de 7 para criar uma mesa de encantamento, uma picareta e uma espada. Você as pega e clica com o botão direito 7 vezes? Ou você clica com o botão direito uma vez e clica com o botão direito duas vezes e vira à esquerda o 7? É tão confuso!

para aqueles de vocês que agora estão confusos, não se preocupem, vou explicar tudo em um segundo

Desafio

Dado o tamanho de uma pilha de itens e a quantidade desejada, determine o menor número de cliques para obter essa quantidade. Você só precisa lidar com até 64 para ambas as entradas e pode assumir que possui infinitos slots de inventário. Você não pode usar o truque de arrastar para distribuir.

Definições

O inventário é uma coleção de slots onde você pode armazenar itens.

Um slot é um espaço de armazenamento em seu inventário onde você pode colocar até um tipo de item.

Uma pilha é um número de itens colocados no mesmo grupo. Para os propósitos deste desafio, uma pilha é simplesmente um monte de itens no mesmo local (portanto, ignore o tamanho da pilha)

O cursor é sua coisa pontuda. Aquele cursor. Pode ter itens "nele"; em outros termos, se você clicou em um slot e pegou itens, os itens que você pegou estão "no cursor" até que você os soltasse.

Especificações

Existem quatro situações possíveis. Você tem um item no cursor ou não, e você clica com o botão esquerdo ou com o botão direito.

Se você não possui um item no cursor e clica com o botão esquerdo do mouse em um slot, escolhe toda a pilha.

Se você não tiver um item no cursor e clicar com o botão direito do mouse em um slot, você pegará metade da pilha, arredondada para cima.

Se você tiver um item no cursor e clicar com o botão esquerdo do mouse em um slot, coloque todos os itens nesse slot. (Para todos os seus jogadores do Minecraft, você não terá> 64 itens para este desafio e todos eles são empilháveis ​​em 64, e você só tem um tipo para que a troca de itens não se aplique aqui)

Se você tiver um item no cursor e clicar com o botão direito do mouse em um slot, coloque um item nesse slot.

Então, você começa com todos os itens fornecidos (primeira entrada ou segunda; pode escolher a ordem) em um slot e deseja terminar com a quantidade desejada (outra entrada) em seu cursor.

Vamos percorrer um exemplo. Digamos que você comece com 17 itens e deseje 7. Primeiro, clique com o botão direito do mouse na pilha, o que significa que você pegou 9 e há 8 nesse slot. Então, se você clicar com o botão direito do mouse na pilha novamente, coloque um item de volta no slot, deixando-o com 8 e o slot com 9. Por fim, clique com o botão direito do mouse novamente e você terá 7 e o slot terá 10. Assim, você retornaria 3(o número de cliques).

Se você conseguir sair do campo de golfe comigo, informe-me e editarei o exemplo: P

Casos de teste

Estes são gerados manualmente, por isso, diga-me se houver algum erro. Eu faço o gerenciamento de inventário clicando com o botão direito do mouse, para não ter experiência com o gerenciamento ideal de inventário: 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

Explicações

Esse desafio pode ser complicado para jogadores que não são do Minecraft, não faço ideia. Aqui estão algumas explicações.

64, 8 -> 5 porque você pega 32 usando o botão direito, coloque-o para baixo, pegue 16, coloque-o e depois 8.

63, 8 -> 5 pela mesma razão.

25, 17 -> 7 porque você pega 13, coloca-o no chão, pega 6 dos 12 restantes, coloca 2 de volta na pilha restante e, em seguida, coloca o 4 no cursor nos 13 e depois pega-os.

Regras

  • Aplicam-se brechas padrão
  • Você pode assumir que 0 <= desired <= given <= 64
  • Você pode receber informações em qualquer ordem e executar E / S em qualquer formato razoável
HyperNeutrino
fonte
1
ae-mod.info
Stephen
Relacionado
AdmBorkBork
2
Então, é como um estado da máquina, que se inicia com um estado de 0,[n], pode transitar: (1) a partir de 0,[a,b,...]a a,[b,...], b,[a,...], ceil(a/2),[floor(a/2),b,...], ou ceil(b/2),[a,floor(b/2),...]; ou (2) a partir de 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]. O desafio é encontrar as transições mínimas possíveis de 0,[g]onde g é dado para t,Londe testá o alvo desejado e Lexiste alguma lista?
Jonathan Allan

Respostas:

2

C ++ , 498 482 457 bytes

Se essa função for chamada apenas uma vez, pode ser 455 bytes.

Descobri que quase todos os compiladores on-line do GCC (incluindo o TIO) me proíbem de omitir o tipo da função f. No entanto, o GCC no meu computador permite isso, e não sei por quê.

Este pode lidar com entradas grandes se um slot puder conter esse número de itens (embora precise de uma matriz maior e provavelmente fique sem 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
        }
    }
}
Colera Su
fonte
1

Geléia , 74 bytes

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

Um programa completo com a primeira entrada (terceiro argumento) a pilha atual e a segunda entrada (quarto argumento) o cursor desejado.

Experimente online! Devido à implementação, isso atinge o tempo limite de 60 segundos do TIO para o25, 17caso de teste. Isso pode ser solucionado com a remoção dos redundantes deixados para o golfe usando este byter de 84 (que filtra pilhas de tamanho zero e classifica as que restamḟ€Ṣ¥0¦€0no final do link 6 e mantém apenas estados únicos em cada etapa com o uso deQ$Main ligação).

Quão?

O programa implementa a máquina de estado definida.
Ele cria o estado original e, em [0, [argument 1]]
seguida, percorre todos os próximos estados possíveis repetidamente
até encontrar um correspondente [argument 2, [...]].

Nota: a entrada do programa está no "Link principal", que é o mais baixo ( 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)
Jonathan Allan
fonte