Teclados de maçaneta flamejante!

21

Bem, o nome de usuário do Doorknob no GitHub, Reddit e outros sites é KeyboardFire . Isso me dá uma idéia...

A tarefa

Você trabalha na KeyboardFire Inc., uma empresa que fabrica teclados especiais. E, com "especial", quero dizer que, sempre que você pressiona uma tecla, algo em sua casa acende! Com a nova série das maçanetas KeyboardFire, os objetos que acendem fogo são maçanetas.

No entanto , devido a estúpidas regulamentações governamentais, seus usuários precisam saber quais maçanetas da casa acenderão.

Considere esta arte ASCII de uma parte de um teclado QWERTY:

1|2|3|4|5|6|7|8|9|0
 q|w|e|r|t|y|u|i|o|p
  a|s|d|f|g|h|j|k|l
   z|x|c|v|b|n|m

(Os |representam os limites entre as chaves.)

Podemos tratar esse desenho ASCII exato como um tipo de "gráfico", em que cada caractere no intervalo [a-z0-9] tem um índice x (horizontal) e y (vertical), onde (0,0)está 1. Por exemplo, a letra dpossui as coordenadas (2,6)(tubos e espaços são incluídos no cálculo de coordenadas).

Agora vamos pensar na casa de cada usuário. Cada casa pode ser vista de cima para baixo como uma arte ASCII de 20x4 (neste mundo onde é legal vender teclados destrutivos, cada casa é do mesmo tamanho). Podemos usar D's' para marcar as posições de cada maçaneta da casa. Aqui está um exemplo:

D         D  D     D
    D               

              D  D  

Vamos chamar isso de "mapa da casa". (Sim, são muitas maçanetas!)

Pressionar qualquer tecla acenderá a maçaneta da porta mais próxima. Por exemplo, se usarmos as coordenadas anteriores da letra d, a maçaneta da porta mais próxima (por distância de Manhattan) estará nas coordenadas (1,4). Esta é a maçaneta da porta que acenderá quando a letra dfor atingida. Se marcássemos a maçaneta em chamas com um F, o resultado seria:

D         D  D     D
    F               

              D  D  

As especificações

Seu programa terá duas entradas:

  • Uma sequência que corresponde ao padrão [a-z0-9]+.
  • Um mapa da casa. Pode ser uma sequência, uma lista de sequências ou algo equivalente.

Você precisa passar por cada letra da string e acender a respectiva maçaneta (altere sua letra para um F). Se a maçaneta da porta mais próxima já estiver pegando fogo, deixe-a como está. Se houver mais de uma maçaneta da maçaneta acesa usando esse método, você poderá acender a que desejar.

Depois que toda a cadeia é processada dessa maneira, você precisa imprimir o mapa da casa resultante.

Código-golfe, o programa mais curto vence. Falhas padrão banidas como de costume.

Exemplo

Corda:

helloworld123

Mapa da casa:

D    D       D     D
    D

              D  D  

Resultados possíveis:

F    F       F     D
    F

              D  F

Ou:

F    D       F     D
    F

              D  F

Ou:

F    F       D     D
    F

              F  F

Ou:

F    D       D     D
    F

              F  F

EDIT: Uh ... há uma razão para eu ter uma resposta, mesmo com uma recompensa de +50? Se você achar as instruções complicadas / vagas, ficaria feliz se você postasse nos comentários ou algo assim ... ou se estou fazendo algo errado ...

EDIT 2: A recompensa expira em menos de um dia! Poste outra coisa! Por favor! POR FAVOR!!!! :(

kirbyfan64sos
fonte
11
Há algumas coisas que eu acho confusas: 1) Por que das cordas (2, 6) e não (2, 2)? 2) Por que o exemplo tem tantas respostas possíveis? 3) Quando você explica como as coisas acenderão fogo, por que você está falando d? Por que não dizer de maneira direta que pressionar pressionará aalguma casa em chamas? Será que dfazê-lo também?
Quelklef 23/11/2015
@Quelklef Isso é um pouco melhor? Obrigado pelo feedback!
kirbyfan64sos
Se 'h' terminar exatamente entre duas maçanetas e 'h' for chamado duas vezes, as duas maçanetas devem estar pegando fogo? ou o programa pode optar por disparar a mesma maçaneta da porta?
Grant Davis
@GrantDavis O programa pode optar por disparar a mesma maçaneta da porta.
kirbyfan64sos

Respostas:

3

JavaScript (ES6), 204 bytes

(s,h)=>[...s].map(c=>(o="1234567890qwertyuiopasdfghjkl_zxcvbnm".search(c),y=o/10|0,x=o%10*2+y,n=a=Math.abs,h.map((k,i)=>k.match(/\s/)||(d=a(x-i%21)+a(y-i/21|0))>n||(n=d,p=i)),h[p]="F"),h=[...h])&&h.join``

Tudo bem, eu atendo. ;)

Explicação

(s,h)=>
  [...s].map(c=>(                     // iterate through each character of the input

    // Get X and Y coordinates of the character input
    o="1234567890qwertyuiopasdfghjkl_zxcvbnm".search(c),
    y=o/10|0,
    x=o%10*2+y,

    // Find the nearest doorknob
    n=                                // n = Manhattan distance to nearest doorknob
      a=Math.abs,
    h.map((k,i)=>                     // iterate through each character of the house
      k.match(/\s/)||                 // do not check distance to whitespace characters
        (d=a(x-i%21)+a(y-i/21|0))>n|| // d = distance to the current doorknob
          (n=d,                       // set the nearest doorknob to this one
          p=i)                        // p = position of the doorknob
    ),
    h[p]="F"                          // update the doorknob to "F" in the house string
  ),h=[...h])&&h.join``               // return the house map as a string

Teste

<input type="text" id="input" value="helloworld123" /><br />
<textarea id="house" rows="4" cols="20">D    D       D     D
    D               
                    
              D  D  </textarea><br />
<button onclick='result.innerHTML=(

(s,h)=>[...s].map(c=>(o="1234567890qwertyuiopasdfghjkl_zxcvbnm".search(c),y=o/10|0,x=o%10*2+y,n=a=Math.abs,h.map((k,i)=>k.match(/\s/)||(d=a(x-i%21)+a(y-i/21|0))>n||(n=d,p=i)),h[p]="F"),h=[...h])&&h.join``

)(input.value,house.value)'>Go</button>
<pre id="result"></pre>

user81655
fonte
2
Finalmente consegui outra resposta !!! : D
kirbyfan64sos
12

Ruby, 229 bytes

->s,m{c=m.flat_map.with_index{|x,i|x.size.times.select{|j|x[j]==?D}.map{|y|[i,y]}}
s.chars{|h|x='1234567890qwertyuiop*asdfghjkl*zxcvbnm'.index h
x,y=(x%10)*2,x/10
a,b=c.min_by{|a,b|(y-a).abs+((y%2>0?x+1:x)-b).abs}
m[a][b]='F'}
m}

Não é muito bom, mas eu só tinha que obter a primeira resposta.

Versão ligeiramente não comentada / comentada:

#!/usr/bin/ruby

f = -> s, m {
    # get knob coords
    c = m.flat_map.with_index {|x, i| x.size.times.select{|j| x[j] == ?D }.map{|y| [i, y] } }
    # for each char in the string
    s.chars {|h|
        # note the asterisks to correct for offsets
        x = '1234567890qwertyuiop*asdfghjkl*zxcvbnm'.index h
        # get un-"staggered" x and y coords
        x, y = (x % 10) * 2, x / 10
        # add one to x for every other row to fit keyboard
        x += 1 if y % 2 > 0
        # find closest knob by Manhattan distance
        a, b = c.min_by{|a, b| (y - a).abs + (x - b).abs }
        # LIGHT IT ON FIRE!
        m[a][b] = 'F'
    }
    # return new map
    m
}

puts f['helloworld123', ['D    D       D     D', '    D', '', '              D  D']]
Maçaneta da porta
fonte