Executar um sobrevôo de Plutão

21

Parabéns! Você acabou de ser contratado pela NASA para trabalhar no novo projeto Horizons 2.

Infelizmente, houve enormes cortes no orçamento recentemente, então a alta gerência decidiu fingir todo o sobrevoo planejado de Plutão (como fizeram nos pousos na lua nos anos 70).

Sua tarefa é escrever um programa que aceite como entrada uma data no formato yyyymmdde forneça uma fotografia falsa de Plutão para essa data. Você pode supor que a data inserida será no ano de 2015 ou 2016.

A fotografia é uma grade 15x15 de caracteres ASCII. Os caracteres na grade têm suas coordenadas xe y dentro do intervalo [-7, 7]- o caractere superior esquerdo está em (-7, -7)enquanto o caractere inferior direito está em (7, 7).

A fotografia será calculada com as seguintes regras:

  • A sonda será a mais próxima de Plutão em 25/12/2015
  • A distância dpara Plutão é dada por esta fórmula:square root of ((difference in days to christmas) ^ 2 + 10)
  • O raio rda imagem de Plutão na foto é dado por:22 / d
  • Um caractere com coordenadas (x, y)na grade deve ser definido como #se x^2 + y^2 <= r^2; caso contrário, ele deve ser definido como espaço.
  • Há estrelas em posições (-3, -5), (6, 2), (-5, 6), (2, 1), (7, -2). As estrelas são representadas por um ponto .e, é claro, são escondidas por Plutão.

Mais uma coisa: o conselho da NASA chegou à conclusão de que a descoberta da vida em Plutão provavelmente resultaria em um aumento substancial do orçamento. Seu programa deve adicionar pistas da vida em Plutão:

  • Quando a distância até Plutão for <= 4, adicione um plutoniano nas coordenadas (-3,-1):(^_^)

Exemplo de fotografia para entrada 20151215: (Seu código deve ter todas as novas linhas como este código)

               

    .          


       #      .
      ###      
     #####     
      ###.     
       #     . 



  .            

Fotografia para entrada 20151225:

               
    #######    
   #########   
  ###########  
 ############# 
 #############.
 ###(^_^)##### 
 ############# 
 ############# 
 ############# 
 ############# 
  ###########  
   #########   
  . #######    

Como comparação, aqui está uma foto do satélite Hydra de Plutão, tirada pela New Horizons. As diferenças são quase imperceptíveis em nossa arte ASCII.

insira a descrição da imagem aqui

Isso é código de golfe, então o código mais curto em bytes vence!

Arnaud
fonte
11
Esse teria sido um desafio perfeito para a linguagem de desenho de arte ASCII em que estou trabalhando. Talvez eu poste uma resposta depois que terminar. :)
ETHproductions
11
@SuperChafouin removi os `s a favor de <pre><code>; sinta-se à vontade para reverter se não gostar.
Justin Justin
11
You can assume the entered date will be in the year 2015 or 2016.Mas então por que especificar um ano?
mınxomaτ 28/09/2015
Posso fazer datas no formato 25/12/2015?
Intrepidcoder #

Respostas:

3

JavaScript (ES6), 237 bytes

f=(n)=>(t=new Date('201'+n[3],n[4]+n[5],n[6]+n[7])/864e5-403805/24,r=484/(t*t+10),(g=(i)=>(++i<8?(h=(j)=>(i*i+j*j<=r?r>30.25&!~i&&'(^_^)'[j+3]||'#':~'p-3-5p62p-56p21p7-2'.indexOf('p'+j+i)?'.':' ')+(++j<8?h(j):''))(-7)+'\n'+g(i):''))(-8))

Demonstração ao vivo . Execute no Firefox.

Versão original

f=function(n) {
    t = (new Date('201'+n[3],''+n[4]+n[5],''+n[6]+n[7]) // Find the time difference in milliseconds,
    - new Date(2015,12,25)) / 864e5;                    // then divide by 86400000 to convert to days.

    r=22 / Math.sqrt(t*t+10);                           // Calculate the radius.

    s=[]; // s is the array that contains each line as a string.

    for(i=-7;i<8;i++)               // Loop through rows.
        for(j=-7,s[i+7]='';j<8;j++) // Loop through columns, appending one character per column.
                                    // s is zero based, so add 7 to the row.
            s[i+7]+=i*i+j*j<=r*r ?  // Choose which character to add to s. 
            (r>5.5&i==-1&&'(^_^)'[j+3]||'#') :  // Add a '#' if the position is inside the radius.
                                                // If distance < 4, then the radius > 5.5
                                                // Then add the face at the right position.
            {'-3-5':1,'62':1,'-56':1,'21':1,'7-2':1} // Add the stars if outside. Create an associative array.
            [j+''+i]?'.':' ';                        // If i concat j is in the array, the expression will be 1, 
                                                     // which is truthy, else it will be undefined, which is falsey.
    return s.join`\n` // Join all the rows with a new-line.
}

Golfe

Foi divertido jogar golfe.

Como não preciso criar um objeto Date, codifiquei o valor em milissegundos para salvar 13 bytes:

t=(new Date('201'+n[3],n[4]+n[5],n[6]+n[7])-new Date(2015,12,25))/864e5 // Before
t=new Date('201'+n[3],n[4]+n[5],n[6]+n[7])/864e5-403805/24 // After

Substitua a matriz associativa por uma sequência delimitada para eliminar 9 bytes:

{'-3-5':1,'62':1,'-56':1,'21':1,'7-2':1}[j+''+i]?'.':' ' // Before
~'p-3-5p62p-56p21p7-2'.indexOf('p'+j+i)?'.':' ' // After

O maior refator foi substituir os loops for por IIFE s aninhados e recursivos para eliminar 10 bytes:

s=[];for(i=-7;i<8;i++)for(j=-7,s[i+7]='';j<8;j++)s[i+7]+= /* Chooses char at i,j */ ;return s.join`\n` // Before
(g=(i)=>(++i<8?(h=(j)=>( /* Chooses char at i,j */ )+(++j<8?h(j):''))(-7)+'\n'+g(i):''))(-8) // After

Eu também me livrei de Math.sqrtmais 8 bytes.

r=22/Math.sqrt(t*t+10),(g=(i)=>(++i<8?(h=(j)=>(i*i+j*j<=r*r?r>5.5 // Before
r=484/(t*t+10),(g=(i)=>(++i<8?(h=(j)=>(i*i+j*j<=r?r>30.25 // After

Problemas

Só consegui a fotografia correta para os casos de teste alterando a data mais próxima para 24/12/2015, e não sei se o problema está no meu código ou na pergunta. Esclareça e atualizarei minha resposta.

Aqui está a minha saída usando as diferenças de 25/12/2015.

Editar: resposta atualizada para usar o Natal como a data mais próxima.

Fotografia para "20151215":

                   

        .          


           #      .
          ###      
         #####     
          ###.     
           #     . 



      .            
                   

Fotografia para "20151225":

                   
        #######    
       #########   
      ###########  
     ############# 
     #############.
     ###(^_^)##### 
     ############# 
     ############# 
     ############# 
     ############# 
      ###########  
       #########   
      . #######    
                   
intrepidcoder
fonte
Meus dois exemplos estavam errados (houve um turno de um dia), eu os corrigi na pergunta. Obrigado por apontar isso!
Arnaud #
3

C # 4.0, 393 bytes

string p(string s){int i=Convert.ToInt32(s),Y=i/10000,m,x,y;s="";i-=Y*10000;m=i/100;i-=m*100;double d=Math.Sqrt(Math.Pow((new DateTime(2015,12,25)-new DateTime(Y,m,i)).Days,2)+10);string o,k=".-3-5.62.-56.21.7-2";for(y=-7;y<8;y++){for(x=-7;x<8;x++){o="#";if(d<=4&&x==-3&&y==-1){o="(^_^)";x+=4;}s+=Math.Pow(x,2)+Math.Pow(y,2)<=Math.Pow(22/d,2)?o:k.Contains("."+x+y)?".":" ";}s+="\n";}return s;}

Exemplo:

string userInput = Console.ReadLine();
Console.WriteLine(p(userInput));

Saída:

20151216


    .


      ###     .
     #####
     #####
     #####
      ###    .



  .

20151224

     #####
   #########
  ###########
  ###########
 #############.
 ###(^_^)#####
 #############
 #############
 #############
  ###########
  ###########
   #########
  .  #####
peter saliente
fonte
2

CJam, 165 bytes

q'-%:i~\0\({X1=29W$2%-X7<X+2%30+?+}fX+\2%-359 6?+:DD*A+mq:Z22Z/_*:R-7:Y];F{-7:X;F{XX*YY*+R>XYF*+[-78II+85H-23]#)'.S?Z4<Y-1=X-4>X2<&&&X-3="(^_^)"L?'#??X):X;}*NY):Y;}*

A primeira parte calcula a diferença do dia e a armazena na Dvariável O resto é um loop duplo que itera através de Xe Y.

Teste aqui

Arnaud
fonte