The CTO's Session

Gonzalo Ruiz de Villa Suárez

CTO @ GFT

GoPro

General Fusion

SnapChat

Twitter

Tesla Motors

Square

SpaceX

Touch Bionics

Carbon3D

 

¿Qué tienen en común?

Software

"It is easier for software to enter other industries that for other industries to hire software people."

 

Benedict Evans

"For decades, BigCo tried to industrialize software. Wrong! It turns out, the future is to softwareize industry."

 

Reginald Braithwaite

PWA

Instant Apps

Rendimiento en la plataforma

Capacidades en el mercado

Nuevas tecnologías

Big Data

Es tan...      2013

Serverless Architectures

↓ costes de operación

↓ costes de desarrollo

↓ costes de escalación

simplicidad de operaciones

más ecológico

vendor control

multitenancy

vendor lock-in

cuestiones de seguridad

"auto" DoS

gestión de estado, testing, tiempo de ejecución

...

Problemas de regresión:  lineales,  logísticas y poisson

Análisis de clusters: K-means, detección de anomalías

Sistemas de recomendación

SVM

Redes neuronales

....

APIs, APIs, APIs...

Quantum Computing

Algoritmo de Grover

Algoritmo de Shor

Programación con conceptos contraintuitivos

Por ejemplo:

  • No localidad
  • Superposición de estados con números complejos

De momento solo podemos programar con 5 qbits y unas 40 operaciones

Evolucionar lo existente

Apostar por un producto

Empezar de cero

Compartir y documentar el proceso de decisión

¿Es tan importante la decisión?

¿O son nuestras acciones posteriores la que la hacen difícil de deshacer?

Conoce a tu equipo

Entrena a tu equipo

Codewars

Codefights

HackerRank

...

Competiciones de programación

♘ vs ♝

/**
 * Determines the victor in a contest between Knight and Bishop.
 * @param {Array} Position of the Knight (e.g., [4, 'C'] for C4)
 * @param {Array} Position of the Bishop (e.g., [5, 'A'] for A5)
 * @returns {String} The winning piece -- 'None' if there are no victors
 */
function knightVsBishop(knightPosition, bishopPosition) {
  var board = new ChessBoard(),
      knight = board.addPiece(Knight),
      bishop = board.addPiece(Bishop),
      bishopWins,
      knightWins;
      
  knight.setPosition(knightPosition);
  bishop.setPosition(bishopPosition);
  
  if (knight.isAbleToTakePiece(bishop)) {
      return 'Knight';
  }
  
  if (bishop.isAbleToTakePiece(knight)) {
      return 'Bishop';
  }
  
  return 'None';
}


/**
 * A container for chess pieces.
 * Traditional chess board, so this has support for x-axis of A through H
 * and a y-axis from 1 to 8.
 * @constructor
 */
function ChessBoard() {
    this.xMap = {
        'a': 1,
        'b': 2,
        'c': 3,
        'd': 4,
        'e': 5,
        'f': 6,
        'g': 7,
        'h': 8
    };
    this.y = [1, 2, 3, 4, 5, 6, 7, 8];
    this.pieces = [];
}

/**
 * Generates a chess piece of the requested type.
 * @param {prototype} The prototype of the requested chess piece. Should extend ChessPiece.
 * @returns {Object} Chess piece of requested type.
 */
ChessBoard.prototype.addPiece = function(type) {
    var piece = Object.create(type.prototype);
    piece.setContainer(this);
    this.pieces.push(piece);
    return piece;
};

/**
 * Generates an extent for the chess board.
 * @returns {Array} Extent for the chess board (e.g., [[0, 0],[8, 8]]).
 */
ChessBoard.prototype.getExtent = function() {
    var extent = [[1, 1],[this.y[0], this.y[this.y.length - 1]]];
        
    for (var key in this.xMap) {
        key = key.toLowerCase();
        if (this.xMap[key] < extent[0][0]) {
            extent[0][0] = this.xMap[key];
        }
        
        if (this.xMap[key] > extent[0][1]) {
            extent[0][1] = this.xMap[key];
        }
    }
    
    return extent;
};

/**
 * Converts a provided position (e.g., [4, 'C']) into a set of x,y coordinates.
 * @param {Array} A position.
 * @returns {Array} x and y coordinates corresponding to the provided position.
 */
ChessBoard.prototype.positionToCoords = function(position) {
    return [this.xMap[position[1].toLowerCase()], position[0]];
};

/**
 * Base type from which other chess pieces type should inherit.
 * @constructor
 */
function ChessPiece() {
}

/**
 * Hook for containers to provide a reference to themselves
 * when adding chess pieces.
 * @param {Object} A container object; e.g., ChessBoard.
 */
ChessPiece.prototype.setContainer = function(container) {
    this.container = container;
};

/**
 * Sets the position of this chess piece.
 * @param {Array} The position (e.g., [4, 'C'] for 4C).
 */
ChessPiece.prototype.setPosition = function(position) {
    this.position = position;
    this.coords = this.container.positionToCoords(position);
};

/**
 * Determines whether or not a requested move is possible
 * within the extent of this piece's container.
 * @param {Array} The requested move, as a set of coordinates (e.g., [4, 5]).
 * @returns {Boolean} True if the move is possible, false otherwise.
 */
ChessPiece.prototype.isMovePossible = function(coordinate) {
    var extent = this.container.getExtent();
    for (var i = 0; i < coordinate.length; i++) {
        for (var j = 0; j < extent.length; j++) {
            if ((coordinate[i] < extent[j][0]) || (coordinate[i] > extent[j][1])) {
                return false;
            }
        }
    }
    return true;
};

/**
 * Returns an array of possible moves within this piece's container.
 * Should be overridden by individual chess piece implementations (e.g., Knight).
 * @returns {Array} An array of possible moves, as coordinates.
 */
ChessPiece.prototype.getPossibleMoves = function() {
    return [];
};

/**
 * Determines whether or not this piece can take the requested piece.
 * @param {ChessPiece} The requested piece.
 * @returns {Boolean} True if this piece can take the requested piece, false otherwise.
 */
ChessPiece.prototype.isAbleToTakePiece = function(piece) {
    var possibleMoves = this.getPossibleMoves(),
        possibleMove;
        
    for (var i = 0; i < possibleMoves.length; i++) {
        possibleMove = possibleMoves[i];
        if ((possibleMove[0] === piece.coords[0]) && (possibleMove[1] === piece.coords[1])) {
            return true;
        }
    }
    
    return false;
};


/**
 * Chess piece representing the Knight type.
 * Can move in a pattern of two along one axis, followed by one along the other axis.
 * Example:
 * 4
 * 3  1 2
 * 2
 * 1  0
 * +ABCDEFGH
 */
function Knight() {
}

Knight.prototype = Object.create(ChessPiece.prototype);

/**
 * Returns an array of possible moves within this piece's container.
 * @returns {Array} An array of possible moves, as coordinates.
 */
Knight.prototype.getPossibleMoves = function() {
    var coords = this.coords,
        moves = [],
        self = this;
    
    [[coords[0] + 1, coords[1] + 2],
     [coords[0] + 2, coords[1] + 1],
     [coords[0] - 1, coords[1] - 2],
     [coords[0] - 2, coords[1] - 1],
     [coords[0] - 1, coords[1] + 2],
     [coords[0] + 1, coords[1] - 2],
     [coords[0] - 2, coords[1] + 1],
     [coords[0] + 2, coords[1] - 1]].forEach(function(possibleMove) {
        if (self.isMovePossible(possibleMove)) {
            moves.push(possibleMove);
        }
    });
    
    return moves;    
};

/**
 * Chess piece representing the Bishop type.
 * Can move in a diagonal line to any edge of the container.
 * Example:
 * 8
 * 7
 * 6       5
 * 5      4
 * 4     3
 * 3    2
 * 2   1
 * 1  0
 * +ABCDEFGH
 */
function Bishop() {
}

Bishop.prototype = Object.create(ChessPiece.prototype);

/**
 * Returns an array of possible moves within this piece's container.
 * @returns {Array} An array of possible moves, as coordinates.
 */
Bishop.prototype.getPossibleMoves = function() {
    var extent = this.container.getExtent(),
        coords = this.coords,
        moves = [],
        self = this,
        inProgress = true,
        previous = coords;
        
    [function() {
        previous = [previous[0] - 1, previous[1] - 1];
        return self.isMovePossible(previous);
    }, function() {
        previous = [previous[0] - 1, previous[1] + 1];
        return self.isMovePossible(previous);
    }, function() {
        previous = [previous[0] + 1, previous[1] - 1];
        return self.isMovePossible(previous);
    }, function() {
        previous = [previous[0] + 1, previous[1] + 1];
        return self.isMovePossible(previous);
    }].forEach(function(isMovePossible) {
        previous = coords,
        inProgress = true;
        while (inProgress) {
            if (isMovePossible()) {
                moves.push(previous);
            } else {
                inProgress = false;
            }
        }
    });
    
    return moves;    
};
function knightVsBishop(knightPosition, bishopPosition) {
  let knightHit = getKnightHitLine(knightPosition);
  let bishopHit = getBishopHitLine(bishopPosition);

  knightPosition = knightPosition.join('');
  bishopPosition = bishopPosition.join('');

  if (knightHit.indexOf(bishopPosition) != -1) {
    return 'Knight';
  } else if (bishopHit.indexOf(knightPosition) != -1) {
    return 'Bishop';
  } else {
    return 'None';
  }
}

let getKnightHitLine = ([num, char]) => {
  let hitLine = [];
  let charCode = char.charCodeAt(0);

  if (
    num - 2 >= boardAxisY.firstNumber &&
    charCode - 1 >= boardAxisX.firstCharCode
  ) {
    let str = (num - 2) + String.fromCharCode(charCode - 1);
    hitLine.push(str);
  }

  if (
    num - 1 >= boardAxisY.firstNumber &&
    charCode - 2 >= boardAxisX.firstCharCode
  ) {
    let str = (num - 1) + String.fromCharCode(charCode - 2);
    hitLine.push(str);
  }

  if (
    num - 2 >= boardAxisY.firstNumber &&
    charCode + 1 <= boardAxisX.lastCharCode
  ) {
    let str = (num - 2) + String.fromCharCode(charCode + 1);
    hitLine.push(str);
  }

  if (
    num - 1 >= boardAxisY.firstNumber &&
    charCode + 2 <= boardAxisX.lastCharCode
  ) {
    let str = (num - 1) + String.fromCharCode(charCode + 2);
    hitLine.push(str);
  }

  if (
    num + 2 <= boardAxisY.lastNumber &&
    charCode + 1 <= boardAxisX.lastCharCode
  ) {
    let str = (num + 2) + String.fromCharCode(charCode + 1);
    hitLine.push(str);
  }

  if (
    num + 1 <= boardAxisY.lastNumber &&
    charCode + 2 <= boardAxisX.lastCharCode
  ) {
    let str = (num + 1) + String.fromCharCode(charCode + 2);
    hitLine.push(str);
  }

  if (
    num + 2 <= boardAxisY.lastNumber &&
    charCode - 1 >= boardAxisX.firstCharCode
  ) {
    let str = (num + 2) + String.fromCharCode(charCode - 1);
    hitLine.push(str);
  }

  if (
    num + 1 <= boardAxisY.lastNumber &&
    charCode - 2 >= boardAxisX.firstCharCode
  ) {
    let str = (num + 1) + String.fromCharCode(charCode - 2);
    hitLine.push(str);
  }

  return hitLine;
};

let getBishopHitLine = ([num, char]) => {
  let hitLine = [];
  let charCode = char.charCodeAt(0);
  let figurePosition = num + char;

  for (
    let i = num, c = charCode;
    i >= boardAxisY.firstNumber && c >= boardAxisX.firstCharCode;
    i--, c--
  ) {
    // to left bottom corner
    let str = i + String.fromCharCode(c);
    if (str !== figurePosition) {
      hitLine.push(str);
    }
  }
  
  for (
    let i = num, c = charCode;
    i >= boardAxisY.firstNumber && c <= boardAxisX.lastCharCode;
    i--, c++
  ) {
    // to right bottom corner
    let str = i + String.fromCharCode(c);
    if (str !== figurePosition) {
      hitLine.push(str);
    }
  }

  for (
    let i = num, c = charCode;
    i <= boardAxisY.lastNumber && c <= boardAxisX.lastCharCode;
    i++, c++
  ) {
    // to left top corner
    let str = i + String.fromCharCode(c);
    if (str !== figurePosition) {
      hitLine.push(str);
    }
  }

  for (
    let i = num, c = charCode;
    i <= boardAxisY.lastNumber && c >= boardAxisX.firstCharCode;
    i++, c--
  ) {
    // to right top corner
    let str = i + String.fromCharCode(c);
    if (str !== figurePosition) {
      hitLine.push(str);
    }
  }

  return hitLine;
};

const boardAxisY = {
  firstNumber: 1,
  lastNumber: 8
};

const boardAxisX = {
  firstCharCode: 65, // letter A
  lastCharCode: 72 // letter H
};
function knightVsBishop(knightPosition, bishopPosition) {
  // Three possible outputs are "Knight", "Bishop", and "None";

  
  var kp = getPos(knightPosition);
  var bp = getPos(bishopPosition);
  
  var ret;
  ret = knight(kp[0], kp[1], bp[0], bp[1]);
  if(ret)
    return 'Knight';
  ret = bishop(bp[0], bp[1], kp[0], kp[1]);
  if(ret)
    return 'Bishop';
  
  return 'None';
}

function bishop(x, y, dx, dy) {
  return Math.abs(x - dx) == Math.abs(y - dy);
}
function knight(x, y, dx, dy) {
  if(x - 2 == dx && y + 1 == dy)
    return true;
  if(x - 1 == dx && y + 2 == dy)
    return true;
  if(x + 1 == dx && y + 2 == dy)
    return true;
  if(x + 2 == dx && y + 1 == dy)
    return true;
  if(x + 2 == dx && y - 1 == dy)
    return true;
  if(x + 1 == dx && y - 2 == dy)
    return true;
  if(x - 1 == dx && y - 2 == dy)
    return true
  if(x - 2 == dx && y - 1 == dy)
    return true
   return false;
}
function getPos(p) {
  var alpha = 'ABCDEFGH';
  var nums = '87654321';
  return [nums.indexOf(p[0]), alpha.indexOf(p[1])];
}
const knightVsBishop = 
  ([nx,ny], [bx,by], diffX, diffY) => ( 
    diffX = Math.abs(nx-bx), 
    diffY = Math.abs(ny.charCodeAt(0)-by.charCodeAt(0)),
    
    diffX == diffY                         ? "Bishop" :
    diffX && diffY && (diffX + diffY) == 3 ? "Knight"
                                           : "None"
  )

¿Sugerencias para entrenar enfoques de alto nivel?

Al final no se trata de ser el primero en tener una idea, sino de implementarla mejor.

Atraer, cuidar y nutrir talento es lo importante.

La tecnología es coyuntural.

¡Gracias!

Créditos de fotos e imágenes:

 

 

  • The Matrix Movie
  • Machine Learning Course Logo by Coursera
  • Amigos: kingofwallpapers.com/friend.html
  • Bob Sponge Imagination: @athumanperson picsart.com
  • Bebe sabio: gifak.net
  • Las fieras combatientes: awegif.com
  • Pendulo de Foucault: Wikimedia Commons
  • Huerto: elhuertodellopez.blogspot.com
  • Hombre sobre cuerda floja: Designed by Freepik
  • Tortitas deliciosas: micocinitadejuguete.blogspot.com.es
  • Mujer Zen: Designed by Jcomp / Freepik 
  • Don Draper en llamas: don-draper-is-zen.tumblr.com

The CTO's Session

By Gonzalo Ruiz de Villa