Reto #1: 🎁 ¡Primer regalo repetido!
function findFirstRepeated ( gifts ) {
let r = ','
for ( const gift of gifts ) {
if ( r . includes ( `,${ gift } ,` ) ) return gift
r += `${ gift } ,`
}
return - 1
}
Reto #2: 🏭 Ponemos en marcha la fábrica
function manufacture ( gifts , materials ) {
return gifts . reduce ( ( acc , gift ) => {
const isManufacturing = [ ...new Set ( gift . split ( '' ) ) ] . every ( ( letter ) =>
materials . includes ( letter )
)
if ( ! isManufacturing ) acc . splice ( acc . indexOf ( gift ) , 1 )
return acc
} , [ ...gifts ] )
}
Reto #3: 😏 El elfo travieso
function findNaughtyStep ( original , modified ) {
for ( let i = 0 ; i < modified . length ; i ++ ) {
if ( original [ i ] !== modified [ i ] ) {
return original . length < modified . length ? modified [ i ] : original [ i ]
}
}
return ''
}
Reto #4: 😵💫 Dale la vuelta a los paréntesis
function decode ( message ) {
if ( message . includes ( '(' ) ) {
message . match ( / \([a-zA-Z\s0-9]*\)/ g) . forEach ( ( match ) => {
message = message . replace (
match ,
match . slice ( 1 , - 1 ) . split ( '' ) . reverse ( ) . join ( '' )
)
} )
message = decode ( message )
}
return message
}
Reto #5: 🛷 El CyberTruck de Santa
function cyberReindeer ( road , time ) {
let road2 = `.${ road . substring ( 1 ) } `
const symbols = {
5 : road2 . replaceAll ( '|' , '*' )
}
const pictures = [ road ]
let x = 0
for ( let i = 1 ; i < time ; i ++ ) {
road2 = symbols [ i ] ?? road2
x += road2 [ x + 1 ] !== '|' ?? 1
pictures . push ( road2 . substring ( 0 , x ) + 'S' + road2 . substring ( x + 1 ) )
}
return pictures
}
Reto #6: 🦌 Los renos a prueba
function maxDistance ( movements ) {
const symbols = {
'>' : ( a ) => a + 1 ,
'<' : ( a ) => a - 1
}
const movementsArray = movements . split ( '' ) . filter ( ( move ) => move !== '*' )
return (
Math . abs (
movementsArray . reduce ( ( acc , movement ) => symbols [ movement ] ( acc ) , 0 )
) +
movements . length -
movementsArray . length
)
}
Reto #7: 📦 Las cajas en 3D
function drawGift ( size , symbol ) {
const pound = '#'
const endLine = '\n'
if ( size === 1 ) return `${ pound } ${ endLine } `
const y0 = pound . repeat ( size )
const middle = size - 2
const yn = `${ pound . repeat ( size ) } ${ symbol . repeat ( middle ) } #`
const upperBox = [ y0 . padStart ( yn . length ) ]
const lowerBox = [ y0 ]
for ( let i = 0 ; i < middle ; i ++ ) {
const row = `#${ symbol . repeat ( middle ) } #${ symbol . repeat ( i ) } #`
upperBox . push ( row . padStart ( yn . length ) )
lowerBox . unshift ( row )
}
return [ ...upperBox , yn , ...lowerBox ] . join ( endLine ) + endLine
}
Reto #8: 🏬 Ordenando el almacén
function organizeGifts ( gifts ) {
const sizes = [ 50 , 10 , 1 ]
return gifts . match ( / \d*[a-z]/ g) . reduce ( ( acc , curr ) => {
let amount = Number ( curr . slice ( 0 , - 1 ) )
const gift = curr . slice ( - 1 )
const store = sizes . reduce ( ( acc , size ) => {
const n = Math . floor ( amount / size )
amount -= n * size
acc . push ( n )
return acc
} , [ ] )
const pallets = `[${ gift } ]` . repeat ( store [ 0 ] )
const boxes = `{${ gift } }` . repeat ( store [ 1 ] )
const bags = `(${ gift . repeat ( store [ 2 ] ) } )` . replace ( '()' , '' )
acc += `${ pallets } ${ boxes } ${ bags } `
return acc
} , '' )
}
Reto #9: 🚦 Alterna las luces
function adjustLights ( lights ) {
const pos = {
0 : '🔴' ,
1 : '🟢'
}
return Math . min (
...lights . reduce (
( acc , light , i ) => {
light !== pos [ i % 2 ] ? acc [ 0 ] ++ : acc [ 1 ] ++
return acc
} ,
[ 0 , 0 ]
)
)
}
Reto #10: 🎄 Crea tu propio árbol de navidad
function createChristmasTree ( ornaments , height ) {
let o = ''
const numOrnaments = ( height * ( height + 1 ) ) / 2
const ornamentsSet = ornaments
. repeat ( Math . ceil ( numOrnaments / ornaments . length ) )
. split ( '' )
. join ( ' ' )
for ( let i = 0 ; i < height ; i ++ ) {
const start = ( ( i * ( i + 1 ) ) / 2 ) * 2
o +=
ornamentsSet . substring ( start , start + i * 2 + 1 ) . padStart ( height + i ) +
'\n'
}
return o + '|' . padStart ( height ) + '\n'
}
Reto #11: 📖 Los elfos estudiosos
function getIndexsForPalindrome ( word ) {
const wordSplitted = word . split ( '' )
const middle = wordSplitted . length / 2
if (
wordSplitted
. slice ( 0 , middle )
. every ( ( c , i ) => c === wordSplitted [ wordSplitted . length - 1 - i ] )
) {
return [ ]
}
for ( let i = 0 ; i < wordSplitted . length ; i ++ ) {
for ( let j = i + 1 ; j < wordSplitted . length ; j ++ ) {
const wordToTest =
word . substring ( 0 , i ) +
word [ j ] +
word . substring ( i + 1 , j ) +
word [ i ] +
word . substring ( j + 1 )
if (
wordToTest
. substring ( 0 , middle )
. split ( '' )
. every ( ( c , i ) => c === wordToTest [ wordToTest . length - 1 - i ] )
) {
return [ i , j ]
}
}
}
return null
}
Reto #12: 📸 ¿Es una copia válida?
function checkIsValidCopy ( original , copy ) {
if ( original . length !== copy . length ) return false
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#+:. '
return ! original . split ( '' ) . some ( ( char , i ) => {
const copyChar = copy . charAt ( i )
const originalIndex = alphabet . indexOf ( char )
const copyIndex = alphabet . indexOf ( copyChar )
return (
( originalIndex < 52 &&
copyIndex < 52 &&
char . toLowerCase ( ) !== copyChar . toLowerCase ( ) ) ||
originalIndex > copyIndex
)
} )
}
Reto #13: ⌚️ Calculando el tiempo
function calculateTime ( deliveries ) {
let leftoverTime =
deliveries . reduce ( ( acc , delivery ) => {
const [ hours , minutes , seconds ] = delivery . split ( ':' )
acc += Number ( hours ) * 3600 + Number ( minutes ) * 60 + Number ( seconds )
return acc
} , 0 ) -
7 * 3600
const sign = leftoverTime < 0 ? '-' : ''
leftoverTime = Math . abs ( leftoverTime )
const leftoverTimeParts = [
`${ Math . floor ( leftoverTime / 3600 ) } ` ,
`${ Math . floor ( ( leftoverTime % 3600 ) / 60 ) } ` ,
`${ leftoverTime % 60 } `
]
. map ( ( part ) => part . padStart ( 2 , '0' ) )
. join ( ':' )
return sign + leftoverTimeParts
}
Reto #14: 🚨 Evita la alarma
function maxGifts ( houses ) {
houses . push ( 0 )
for ( let i = houses . length - 4 ; i >= 0 ; i -- ) {
houses [ i ] += Math . max ( houses [ i + 2 ] , houses [ i + 3 ] )
}
return Math . max ( houses [ 0 ] , houses [ 1 ] )
}
Reto #15: ↔️ Robot autónomo
function autonomousDrive ( store , movements ) {
const pathSymbols = {
freeWay : '.' ,
barrier : '*' ,
robotPosition : '!'
}
const movementsSymbols = {
R : [ 1 , 0 ] ,
L : [ - 1 , 0 ] ,
U : [ 0 , - 1 ] ,
D : [ 0 , 1 ]
}
let x
let y
for ( let i = 0 ; i < store . length ; i ++ ) {
const xAux = store [ i ] . indexOf ( pathSymbols . robotPosition )
if ( xAux !== - 1 ) {
x = xAux
y = i
break
}
}
store [ y ] = store [ y ] . replace ( '!' , '.' )
for ( const movement of movements ) {
const [ x1 , y1 ] = movementsSymbols [ movement ]
const yAux = y + y1
if ( ! store [ yAux ] ) continue
const xAux = x + x1
const nextSymbol = store [ yAux ] [ xAux ]
if ( ! nextSymbol || nextSymbol === pathSymbols . barrier ) continue
x = xAux
y = yAux
}
store [ y ] =
store [ y ] . substring ( 0 , x ) +
pathSymbols . robotPosition +
store [ y ] . substring ( x + 1 )
return store
}
Reto #16: ❌ Despliegue en viernes
function transformTree ( tree ) {
if ( ! tree . length ) return null
function child ( parent ) {
const value = tree [ parent ]
const leftChild = ( parent + 0.5 ) * 2
const rightChild = leftChild + 1
if ( parent >= tree . length || value === null ) return null
return {
value,
left : leftChild >= tree . length ? null : child ( leftChild ) ,
right : rightChild >= tree . length ? null : child ( rightChild )
}
}
return {
value : tree [ 0 ] ,
left : child ( 1 ) ,
right : child ( 2 )
}
}
Reto #17: 🛷 Optimizando el alquiler
function optimizeIntervals ( intervals ) {
intervals . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) ;
const result = [ intervals [ 0 ] ] ;
for ( const val of intervals . slice ( 1 ) ) {
const [ start , end ] = val ;
const max = result [ result . length - 1 ] [ 1 ] ;
start > max
? result . push ( val )
: ( result [ result . length - 1 ] [ 1 ] = Math . max ( end , max ) ) ;
}
return result ;
}
Reto #18: 🔢 El reloj digital
function drawClock ( time ) {
const digits = {
0 : [ '***' , '* *' , '* *' , '* *' , '* *' , '* *' , '***' ] ,
1 : [ ' *' , ' *' , ' *' , ' *' , ' *' , ' *' , ' *' ] ,
2 : [ '***' , ' *' , ' *' , '***' , '* ' , '* ' , '***' ] ,
3 : [ '***' , ' *' , ' *' , '***' , ' *' , ' *' , '***' ] ,
4 : [ '* *' , '* *' , '* *' , '***' , ' *' , ' *' , ' *' ] ,
5 : [ '***' , '* ' , '* ' , '***' , ' *' , ' *' , '***' ] ,
6 : [ '***' , '* ' , '* ' , '***' , '* *' , '* *' , '***' ] ,
7 : [ '***' , ' *' , ' *' , ' *' , ' *' , ' *' , ' *' ] ,
8 : [ '***' , '* *' , '* *' , '***' , '* *' , '* *' , '***' ] ,
9 : [ '***' , '* *' , '* *' , '***' , ' *' , ' *' , '***' ] ,
':' : [ ' ' , ' ' , '*' , ' ' , '*' , ' ' , ' ' ]
}
return time
. split ( '' )
. reduce (
( acc , curr ) => {
const digit = digits [ curr ]
for ( let i = 0 ; i < 7 ; i ++ ) {
acc [ i ] . push ( digit [ i ] )
}
return acc
} ,
[ [ ] , [ ] , [ ] , [ ] , [ ] , [ ] , [ ] ]
)
. map ( ( row ) => row . join ( ' ' ) . split ( '' ) )
}
Reto #19: 💣 Enfrenta el sabotaje
function revealSabotage ( store ) {
for ( const [ i , row ] of store . entries ( ) ) {
for ( const [ j , col ] of row . entries ( ) ) {
if ( col === '*' ) continue
const nextRow = store [ i + 1 ]
const prevRow = store [ i - 1 ]
const adjacentCells = [
prevRow ?. [ j - 1 ] ,
prevRow ?. [ j ] ,
prevRow ?. [ j + 1 ] ,
row [ j - 1 ] ,
row [ j + 1 ] ,
nextRow ?. [ j - 1 ] ,
nextRow ?. [ j ] ,
nextRow ?. [ j + 1 ]
]
const count = adjacentCells . reduce (
( acc , curr ) => acc + + ( curr === '*' ) ,
0
)
if ( count !== 0 ) {
row [ j ] = `${ count } `
}
}
}
return store
}
Reto #20: 🏋️♂️ Distribuye el peso
function distributeGifts ( weights ) {
const ms = [
[ - 1 , 0 ] ,
[ 1 , 0 ] ,
[ 0 , - 1 ] ,
[ 0 , 1 ] ,
[ 0 , 0 ]
]
return weights . map ( ( _ , i ) =>
weights [ i ] . map ( ( _ , j ) => {
let l = 0
let s = 0
ms . forEach ( ( k ) => {
const x = j + k [ 0 ]
const y = i + k [ 1 ]
const weight = weights [ y ] && weights [ y ] [ x ]
if ( weight ) {
s += weights [ y ] [ x ]
l ++
}
} )
return Math . round ( s / l )
} )
)
}
Reto #21: 🪐 Mensaje binario
function findBalancedSegment ( message ) {
let t = 0
let r = [ 0 , 0 ]
for ( let i = 0 ; i < message . length ; i ++ ) {
let l = message . length - i
let s = message
. slice ( i , message . length + 1 )
. reduce ( ( acc , curr ) => acc + curr , 0 )
for ( let j = message . length ; j > i ; j -- ) {
l --
if ( l <= r [ 1 ] ) continue
s -= message [ j ] || 0
if ( s * 2 === l + 1 && s > t ) {
t = s
r = [ i , l ]
}
}
}
return r [ 1 ] ? [ r [ 0 ] , r [ 0 ] + r [ 1 ] ] : [ ]
}
Reto #22: 🚂 Lenguaje de programación
function compile ( code ) {
let c = 0
let lr = null
const cs = code . split ( '' )
for ( let i = 0 ; i < cs . length ; i ++ ) {
const b = cs [ i ]
if ( b === '%' ) {
lr = i
continue
}
if ( b === '+' ) c ++
if ( b === '-' ) c --
if ( b === '*' ) c *= 2
if ( b === '<' && lr !== null ) {
cs [ i ] = ''
i = lr
continue
}
if ( b === '¿' && c <= 0 ) {
i = cs . findIndex ( ( b2 , i2 ) => b2 === '?' && i2 > i )
continue
}
}
return c
}
Reto #23: 🍽️ La comida de Navidad
function organizeChristmasDinner ( dishes ) {
return Object . entries (
dishes . reduce ( ( acc , dish ) => {
dish . slice ( 1 ) . forEach ( ( ingredient ) => {
if ( ! acc [ ingredient ] ) acc [ ingredient ] = [ ]
acc [ ingredient ] . push ( dish [ 0 ] )
} )
return acc
} , { } )
) . reduce ( ( acc , [ key , value ] ) => {
if ( value . length > 1 ) acc . push ( [ key , ...value . sort ( ) ] )
return acc
} , [ ] ) . sort ( )
}
Reto #24: 🪜 Brincos en la escalera
function getStaircasePaths ( steps , maxJump ) {
const arr = [ ]
const f = ( s , g ) => {
if ( s === 0 ) return arr . push ( g )
for ( let i = 1 ; i <= Math . min ( s , maxJump ) ; i ++ ) {
if ( s > 0 ) f ( s - i , g . concat ( [ i ] ) )
}
}
f ( steps , [ ] )
return arr
}
Reto #25: 🗺️ Calculando distancias
function travelDistance ( map ) {
let mapCleaned = map . replaceAll ( ' ' , '' )
const mapRowLength = mapCleaned . split ( '\n' ) [ 0 ] . length
mapCleaned = mapCleaned . replaceAll ( '\n' , '' )
const childrenPositions = mapCleaned
. replace ( 'S' , '' )
. replaceAll ( '.' , '' )
. split ( '' )
. sort ( )
const positions = [ 'S' , ...childrenPositions ]
return positions . reduce ( ( acc , curr , index ) => {
if ( index === positions . length - 1 ) return acc
const currPosition = mapCleaned . indexOf ( curr )
const nextPosition = mapCleaned . indexOf ( positions [ index + 1 ] )
const rowDiff =
Math . floor ( currPosition / mapRowLength ) -
Math . floor ( nextPosition / mapRowLength )
const colDiff =
( currPosition % mapRowLength ) - ( nextPosition % mapRowLength )
return acc + Math . abs ( rowDiff ) + Math . abs ( colDiff )
} , 0 )
}