Gonzalo Ruiz de Villa Suárez
CTO @ GFT
GoPro
General Fusion
SnapChat
Tesla Motors
Square
SpaceX
Touch Bionics
Carbon3D
¿Qué tienen en común?
"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
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
....
Quantum Computing
Algoritmo de Grover
Algoritmo de Shor
Programación con conceptos contraintuitivos
Por ejemplo:
De momento solo podemos programar con 5 qbits y unas 40 operaciones
Evolucionar lo existente
Apostar por un producto
Empezar de cero
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?
La tecnología es coyuntural.
Créditos de fotos e imágenes: