# The learning game - Machine Learning #1
Growing up you would have learnt a lot of things like not to stand in fire, to drink food and eat water and not to jump off very tall things But Machines have it difficult they cannot learn for themselves we have to tell them what to do, why don't we give them a chance to learn it for themselves?

### Task
Your task is to finish the Machine object. What the machine object must do is learn from its mistakes! The Machine will be given a command and a number you will return a random action. After the command has returned you will be given a response (true/false) if the response is true then you have done good, if the response is false then the action was a bad one. You must program the machine to learn to apply an action to a given command using the reponse given. Note: It must take no more than 20 times to teach an action to a command also different commands can have the same action.

### Info
- In the preloaded section there is a constant called ```ACTIONS``` it is a function that returns the 5 possible actions.
- In Java, this a constant ```Actions.FUNCTIONS``` of type ```List>```. 
- In C++, the actions can be accessed by ```get_action(i)(unsigned int num)``` where i chooses the function (and therefore can range from 0 to 4) and num is its argument.
- In python ```ACTIONS()``` returns a list of lambdas.
- In Golang ```Actions()``` retruns a function slice ```[]func(int) int```

Difficulty: interview

Starter code:

def __init__(self):
	

Solutions:
class Machine:
    def __init__(self):
        self.cmd = dict()
        self._actions = [lambda x: x + 1, lambda x: 0, lambda x: x / 2, lambda x: x * 100, lambda x: x % 2]

    def command(self, cmd, num):
        self.last_cmd = cmd
        if cmd  in self.cmd:
            return self._actions[self.cmd[cmd]](num)
        else:
            self.cmd[cmd] = 0
        return self._actions[self.cmd[cmd]](num)

    def response(self,res):
        if res == False:
            self.cmd[self.last_cmd] += 1

class Machine:
    def __init__(self):
        self.action_for_cmd = {}
        self._actions = ACTIONS()
    
    def command(self, cmd, num):
        self.last_cmd = cmd
        if cmd not in self.action_for_cmd:
            self.action_for_cmd[cmd] = 0
        return self._actions[self.action_for_cmd[cmd]](num)
    
    def response(self,res):
        if not res:
            self.action_for_cmd[self.last_cmd] += 1

class Machine:

    def __init__(self):
        self.actptr = 0
    
    def command(self, cmd, num):
        return ACTIONS()[(cmd + self.actptr) % 5](num)
        
    def response(self,res):
        if not res: self.actptr += 1


class Machine:
    """Class which is taught to use a specific function based on responses."""
    
    def __init__(self):
        """Create a dictionary which has the possivle command options as entries and they all point towards a 
        specific function to use."""
        self.lambdas = ACTIONS()
        self.commands = dict.fromkeys([x for x in range(len(self.lambdas))], 0)
        self.last_command = None
    
    
    def command(self, cmd, num):
        """Calculates number with the function the cmd in the won dictionary currently points to.
        
        :param cmd: used to reference which function to use
        :param num: which should be calculated
        :returns: calculated value
        """
        cmd = cmd % len(self.lambdas) # This was very annoying, since it is done in the sample tests but not in the random tests
        self.last_command = cmd
        return self.lambdas[self.commands[cmd]](num)

    
    def response(self,res):
        """Changes the function used for a specific cmd number if the machine got a negative response for his last command.
        """
        if not res:
            self.commands[self.last_command] += 1 % len(self.lambdas)


class Machine:
    def __init__(self):
        self.actions = ACTIONS()
        self.command_to_action_map = {}    # This is the mapping that the machine has to learn
        self.current_command = 0

    def command(self, cmd, num):
        if not (cmd in self.command_to_action_map):
            self.command_to_action_map[cmd] = 0
            
        self.current_command = cmd
        action_index = self.command_to_action_map[cmd]
        return self.actions[action_index](num)

    def response(self,res):
        # If the answer was not correct lets update the action mapped to that command to the next possible action
        if res == False:
            self.command_to_action_map[self.current_command] += 1
            self.command_to_action_map[self.current_command] %= len(self.actions)

import sys

class Machine:
    def __init__(self):
        self._actions = [lambda x:x+1, lambda x:0, lambda x: x/2, lambda x: x*100, lambda x: x%2]
        self.action_mapping = {}
        self.last = 0
        
    def command(self, cmd, num):
        self.last = cmd
        if cmd not in self.action_mapping:
            self.action_mapping[cmd] = 0
        return self._actions[self.action_mapping[cmd]](num)
        
    def response(self,res):
          if not res:
            self.action_mapping[self.last] += 1

class Machine:
    def __init__(self):
        _actions = ACTIONS()
        self.actions ={}
    def command(self, cmd, num):
        self.cmd=cmd
        self.actions[cmd] = self.actions.get(cmd,ACTIONS())
        return self.actions[cmd][0](num)
    def response(self,res):
        if not res:
            self.actions[self.cmd]=self.actions[self.cmd][1:]

from collections import defaultdict

class Machine:
    def __init__(self):
        self.translate = defaultdict(int)
        self.last_cmd = None
        
    def command(self, cmd, num):
        self.last_cmd = cmd
        return _actions[self.translate[cmd]](num)
        
    def response(self, res):
        if not res:
            self.translate[self.last_cmd] += 1

class Machine:
    def __init__(self):
        self.cmd = dict()

    def command(self, cmd, num):
        self.last_cmd = cmd
        if cmd  in self.cmd:
            return _actions[self.cmd[cmd]](num)
        else:
            self.cmd[cmd] = 0
        return _actions[self.cmd[cmd]](num)

    def response(self,res):
        if res == False:
            self.cmd[self.last_cmd] += 1