How to build a unique number based on several numbers

3

Good morning, to explain better what I want to know is to let you know so I can use it.

With a class called Personaje I want to know how it is dressed, it would be enough to create several variables where a number is stored that identifies the sprite that will be used, example:

Personaje:
    cabeza = 5
    cuerpo = 3
    brazos = 88
    pantalon = 23
    zapatos = 18

But I would like to know if there is any efficient way to do it with just one variable, like this:

Personaje:
    sprite = 183

Now what I want to know is how I can do to build a number based on the 5 values mentioned above and then break it down and get the 5 values again. Is there already a formula or algorithm for this?

This is more for knowing that out of necessity, I know that using arrays would solve everything easily.

I edit for those who are responding : Their solutions are good and very correct, but it's not exactly what I want, my solution should be more for mathematical knowledge / algorithms / equations than for programming solutions , the solutions that you are giving me are basically to create arrangements or types of data / classes. An example of what I want would be something similar to this:

ancho = 20
alto = 15
tamaño = ancho * alto
mapa = Array.new(tamaño)
mapa[x + y * ancho] = tile_id

Something similar to that I would like to achieve, in the only solution that I can get with my knowledge would be creating a buffer, so that:

buffer = "000000000000000" #=> Cada 3 digitos es un valor

example of use:

cabeza = 5
cuerpo = 49
brazos = 0
pantalon = 186
zapatos = 650
buffer += cabeza #=> "005 000 000 000 000"
buffer += cuerpo #=> "005 049 000 000 000"
buffer += brazos #=> "005 049 000 000 000"
buffer += pantalon #=> "005 049 000 186 000"
buffer += zapatos #=> "005 049 000 186 650"

valor final de buffer = "005049000186650"

It is a solution, but still you have to establish the size of the buffer and it is not a mathematical formula that I would like to know, thank you all for your comments and answers! :)

    
asked by Andrek 19.07.2017 в 23:49
source

8 answers

3

For me, who solves this better is C / C ++, through union

In a union different structures and types share the same memory space, so you can handle the information separately or all together. For example:

union Personaje
{
    struct 
    {
        char Cara;
        char Pelo;
        char Cuerpo;
        char Piernas;
    } grupos;
    int32_t codigo;
};

int main()
{
    Personaje prueba;

    prueba.grupos.Cara = 21;
    prueba.grupos.Pelo = 88;
    prueba.grupos.Cuerpo = 15;
    prueba.grupos.Piernas = 77;

    std::cout << prueba.codigo << std::endl; // Esto devuelve 1292851221

    prueba.codigo = 1292851222; // Si cambio el valor....

    std::cout << (int)prueba.grupos.Cara << std::endl;
    std::cout << (int)prueba.grupos.Pelo << std::endl;
    std::cout << (int)prueba.grupos.Cuerpo << std::endl;
    std::cout << (int)prueba.grupos.Piernas << std::endl;

}

The output of the previous example would be:

1292851221 
22 
88 
15 
77

In this example, a structure (groups) of 4 bytes (each char is a byte ) and an integer (code) equally 4 bytes share the same memory:

 -Byte- -Byte- -Byte- -Byte- 
-----------------------------
| Cara | Pelo | Cuer | Pier | <- Si accedes por la struct grupos
-----------------------------
|        c o d i g o        | <- Si accedes por la variable codigo
-----------------------------    
<--------- 32 bits --------->

This method has the advantage that you do not have to carry out transformations or calculations, any change you make in one of the variables immediately affects all the others.

    
answered by 20.07.2017 / 00:27
source
0

It is possible, what you should do is first define all your catalogs with their respective values:

  • Head
  • Body
  • Arms
  • Pants
  • Shoes

Since you have defined them, you must create another Sprite's catalog that will contain all the possible combinations that may exist of your elements and you can create your identifier number based on the identifiers of each element although I do not recommend generating the identifier Sprite in this way since it could be repeated, better generate it in another way and assign it to each combination so when you generate that Sprite you can know what elements it contains.

I recommend studying probability, simulation and generation of pseudo-randomizations, I could guide you better.

    
answered by 20.07.2017 в 00:03
0

Since you will certainly be using object-oriented programming, it occurs to me that it would be good to follow the programming paradigm and use an object to solve your problem. Certainly using arrays is a possible solution.

What you can do is create a class called sprite , instantiate the class and "save" in the object the numbers or variables you need. In a pseudolanguage (invented for this occasion hahaha), you could think of something like this:

clase Sprite
    definir constructor(a,b,c,d,e)
        cabeza = a
        cuerpo = b
        brazos = c
        pantalon = d
        zapatos = e

Then in your class Personaje you can have a property that is of type Sprite , something like this:

clase Personaje
    definir constructor(Sprite a)
        sprite = a

So, an example of a functional code in this "pseudolanguage" could be the following:

s = new Sprite(5,3,88,23,18)
p = new Personaje(s)

And then you can now refer and know the values of body parts directly from the object, with reference to a single variable that is p . Following this paradigm, you can easily scale the code in case you would need more body parts or something like that, and also just need the variable p .

This is the idea. You can translate this idea very easily into any object-oriented programming language. I hope I have helped you.

    
answered by 20.07.2017 в 00:14
0

From what I understood, when you create a new character you can pass a dictionary of types:

class Personaje:
    def __init__(self, tipos):
        self.tipos = tipos

    def get_sprite_types(self):
        # Retorna una lista o array de los tipos de vestimenta usados
        return list(self.tipos.keys())

    def get_sprite_values(self):
        # Retorna una lista o array de los valores de cada vestimenta
        return [self.tipos[x] for x in self.tipos]

    def get_sprite(self):
        # Calcula la suma de los valores de cada tipo de vestimenta
        return sum(self.get_sprite_values())

Now, to create the character:

>>> tipos = {'pantalon': 23, 'zapatos': 18}
>>> personaje = Personaje(tipos)
>>> personaje.tipos
{'zapatos': 18, 'pantalon': 23}
>>> personaje.get_sprite()
41
>>> personaje.get_sprite_values()
[18, 23]
>>> personaje.get_sprite_types()
['zapatos', 'pantalon']
>>> tipos_usados = personaje.get_sprite_types()
>>> print('Vestimenta usada para el personaje: {}'.format(', '.join(tipos)))
Vestimenta usada para el personaje: zapatos, pantalon

It's in Python but I think it's pretty understandable. The idea is that after creating the character you have access to each type of clothing with which it was created and also to the total value of sprite .

    
answered by 20.07.2017 в 00:16
0

It just happened to me, I do not see it as efficient but I suppose it 'fits' in what you're looking for, have not you thought about concatenating?

Personaje:
    cabeza = 5
    cuerpo = 3
    brazos = 88
    pantalon = 23
    zapatos = 18

Before concatenating, reserve the first two digits (or whatever you want) to indicate how many zeros it is.

For example: 0350003000880002300018

Here you indicate with the first two digits ( 03 = 3) that there are three zeros as a separator, that is, each time the program encounters three consecutive zeros, it moves to the next field.

Broken down:

03 5 -000- 3 -000- 88 -000- 23 - 000 - 18

With a divider of 6 it would be: 0650000003000000880000002300000018

06 5 -000000- 3 -000000- 88 -000000- 23 - 000000 - 18

The separator you adjust according to the zeros that your program has, in this case as no value has a zero, the most appropriate separator would be 1: 01503088023018

    
answered by 20.07.2017 в 01:20
0

I am answering my own question is because I found a solution based on the response of @David Isla.

This solution was made in Ruby and is a way of doing it without using C / C ++ Unions, basically what I do is transform the 5 variables into binaries, and then add it, then the sum is transformed to its equivalent in number and ready, then it only remains to transform that number back to binary and grab the bytes that correspond to each number, I'll give you an example of what I did in Ruby:

# Esta funcion sirve para obtener el valor binario de un numero en forma de string.
# number => Numero a obtener el valor binario.
def get_binary(number)
    binary = number.to_s(2) # Retorna el string en binario, tambien se puede usar: binary = "%b" % number
    byte_size = 1 * 8

    # Si el tamaño de un binario es menor que el tamaño dado se agregan ceros(0) al inicio del binario, ejemplo:
    # byte_size = 8
    # binary = 18.to_s(2) #=> "10010" solo 5 digitos, faltan 3 para que sea del tamaño de byte_size
    # binary = "000" + "10010" = "00010010" = 18
    #
    # Para ahorrarnos todo esto podemos simplemente usar: "%tamaño_en_bytesb" % number
    # Ejemplo: "%08b" % number
    if binary.size < byte_size
        binary = ("0" * (byte_size - binary.size)) + binary
    end
    return binary[0...byte_size]
end

class Player
    attr_accessor :head, :body, :arms, :pants, :boots
    # Retorna la suma binaria de todos los numeros requeridos
    def get_seed
        return (get_binary(self.head) + get_binary(self.body) + get_binary(self.arms) + get_binary(self.pants) + get_binary(self.boots)).to_i(2)
    end
    # Transforma la semilla en binario y va retirando la cantidad de bytes desde el final de el codigo binario.
    # Ejemplo:
    # 1. [                                                       ] = "1001000011010010000010101100001100011"
    # 2. ["01100011"                                             ] = "10010000110100100000101011000"
    # 3. ["01100011", "01011000"                                 ] = "100100001101001000001"
    # 4. ["01100011", "01011000", "01000001"                     ] = "1001000011010"
    # 5. ["01100011", "01011000", "01000001", "00011010"         ] = "10010"
    # 6. ["01100011", "01011000", "01000001", "00011010", "10010"]
    # 7. [        98,         88,         65,         26,      18]
    def set_seed(seed)
        binary = seed.to_s(2) # El binario es la representacion binaria de la semilla en string.
        byte_size = 1 * 8
        array = []
        while true
            # Salir del bucle si la semilla esta vacia.
            if binary.size == 0
                break
            end
            # Si el tamaño de los binario es menor que el que se desea sacar significa que es el ultimo elemento
            # asi que se termina el bucle.
            if binary.size < byte_size
                value = binary.to_i(2)
                array.push(value)
                break
            end
            # Sacar un valor de el binario.
            value = (binary[binary.size - byte_size...binary.size]).to_i(2)
            binary = binary[0...binary.size - byte_size]
            array.push(value)
        end
        array.reverse!
        self.head = array[0]
        self.body = array[1]
        self.arms = array[2]
        self.pants = array[3]
        self.boots = array[4]
    end
end

personaje = Player.new
personaje.head = 18
personaje.body = 26
personaje.arms = 65
personaje.pants = 88
personaje.boots = 98
p personaje.get_seed #=> 77749901410
print("\n")

personaje2 = Player.new
personaje2.set_seed(personaje.get_seed) #=> 77749901410
p personaje2.head  #=> 18
p personaje2.body  #=> 26
p personaje2.arms  #=> 65
p personaje2.pants #=> 88
p personaje2.boots #=> 98
print("\n")

personaje2.set_seed(personaje.get_seed + 1) #=> 77749901411
p personaje2.head  #=> 18
p personaje2.body  #=> 26
p personaje2.arms  #=> 65
p personaje2.pants #=> 88
p personaje2.boots #=> 99 <<<< Cambio

For those who program in Ruby, I tell them to program it so that it is more universal in terms of programming languages. Thank you very much everyone for your answers were very helpful, good luck! :)

    
answered by 20.07.2017 в 04:16
0

As each number can be broken down in a unique way into the product of cousins. Assign to each party a range of prime numbers that can not be repeated and must be continuous to identify which rank corresponds to each one.

This is my code in c #.

using System;
using System.Collections.Generic;

namespace ConsolePersonaje
{
    /// <summary>
    /// https://es.stackoverflow.com/questions/88139/como-construir-un-numero-unico-a-base-de-varios-numeros
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            int[] cabezas = new int[] { 2, 3, 5, 7 };
            int[] cuerpos = new int[] { 13, 17, 19 };
            int[] brazos = new int[] { 23, 29, 31, 37 };
            /*Cada numero se descompone como productos de primos de manera unica.*/
            int unico = cabezas[1] * cuerpos[2]* brazos[0];

            Personaje person = new Personaje(unico);

            int cabeza = person.Cabeza;
            int cuerpo = person.Cuerpo;
            int brazo = person.Brazo;

            Console.WriteLine(String.Format("Cabeza: {0} Cuerpo: {1} Brazo: {2}", cabeza, cuerpo, brazo));
            Console.ReadKey();
        }

        public class Personaje
        {
            private int _numero;
            private List<int> _factores;

            public Personaje(int p)
            {
                this._numero = p;
                this._factores = FactoresPrimos(p);
            }

            /*Funcion que descompone en factores primos*/
            public List<int> FactoresPrimos(int p)
            {
                List<int> result = new List<int>();
                if (p == 1)
                    result.Add(p);
                else
                {
                    while (p > 1)
                    {
                        int div = 2;

                        while (p % div != 0)
                            div++;

                        p = p / div;
                        result.Add(div);
                    }
                }

                return result;
            }

            public int Cabeza
            {
                get
                {
                    foreach (var fac in this._factores)
                    {
                        //rango de cabezas: 2, 3, 5, 7
                        if (fac >= 2 && fac <= 7)
                        {
                            return fac;
                        }
                    }

                    return 0;
                }
            }

            public int Cuerpo
            {
                get
                {
                    foreach (var fac in this._factores)
                    {
                        //rango de cuerpos: 13, 17, 19
                        if (fac >= 13 && fac <= 19)
                        {
                            return fac;
                        }
                    }

                    return 0;
                }
            }

            public int Brazo
            {
                get
                {
                    foreach (var fac in this._factores)
                    {
                        //rango de Brazos
                        //23, 29, 31, 37
                        if (fac >= 23 && fac <= 37)
                        {
                            return fac;
                        }
                    }

                    return 0;
                }
            }
        }
    }
}
    
answered by 26.07.2017 в 23:08
0

I answer my question again to show another possible solution shown by @ Urres.Alejandro, here the code in Ruby:

# Metodo escrito por: https://es.stackoverflow.com/users/30418/urres-alejandro
def factores_primos(n)
    result = []
    if n == 1
        result.push(n)
    else
        while n > 1
            div = 2
            while(n % div != 0)
                div += 1
            end
            n = n / div
            result.push(div)
        end
    end
    return result
end

# Detecta una cantidad de numeros primos.
def numeros_primos(cantidad)
    result = []
    n = 1
    while(result.size < cantidad)
        a = 0
        for div in 1..n
            if n % div == 0
                a += 1
            end
        end
        result.push(n) if a == 2
        n += 1
    end
    return result
end

class Player
    primos = numeros_primos(1000)
    HEAD = primos[0...200] #=> 0 hasta 199
    BODY = primos[200...400] #=> 200 hasta 399
    ARMS = primos[400...600] #=> 400 hasta 599
    PANTS = primos[600...800] #=> 600 hasta 799
    BOOTS = primos[800...1000] #=> 800 hasta 999
    def initialize(head = 0, body = 0, arms = 0, pants = 0, boots = 0)
        @head = head
        @body = body
        @arms = arms
        @pants = pants
        @boots = boots
    end
    def get_seed
        return (HEAD[@head] * BODY[@body] * ARMS[@arms] * PANTS[@pants] * BOOTS[@boots])
    end
    def set_seed(seed)
        ids = factores_primos(seed)

        # El metodo Array#index retorna la hubicacion en el array del valor que pases, ejemplo:
        # array = ["Juan", "Pedro", "Gabriel"]
        # array.index("Juan") #=> 0
        # array.index("Pedro") #=> 1
        # array.index("Gabriel") #=> 2
        @head = HEAD.index(ids[0])
        @body = BODY.index(ids[1])
        @arms = ARMS.index(ids[2])
        @pants = PANTS.index(ids[3])
        @boots = BOOTS.index(ids[4])
    end
    # Metodo llamado cuando se quiere mostrar una clase en Ruby.
    def inspect
        string = "Head: #{@head}\n"
        string += "Body: #{@body}\n"
        string += "Arms: #{@arms}\n"
        string += "Pants: #{@pants}\n"
        string += "Boots: #{@boots}"
    end
end

player1 = Player.new(4, 180, 100, 70, 68)
p "Semilla del 1 jugador: #{player1.get_seed}" #=> 3484027755527363

player2 = Player.new
player2.set_seed(player1.get_seed) #=> Head: 4
                                   #=> Body: 180
                                   #=> Body: 180
                                   #=> Arms: 100
                                   #=> Pants: 70
                                   #=> Boots: 68
p "Semilla del 2 jugador: #{player2.get_seed}" #=> 3484027755527363

p player2
    
answered by 28.07.2017 в 00:34