Carga do telefone celular


10

Desafio Tomado com permissão do meu Concurso de Desafio de Código da Universidade


A dependência que temos dos telefones celulares nos faz carregá-los todas as noites até o nível máximo da bateria, para não correr o risco de ficar sem energia até a metade do dia seguinte. Existem até pessoas que, quando veem uma saída gratuita durante o dia, cobram pelo que pode acontecer.

Eu sou um deles.

Ao longo dos anos, aprimorei minha técnica para não carregar a bateria ao máximo todas as noites. Com minhas rotinas repetitivas perfeitamente conhecidas, sou claro a que horas do dia poderei fazer essas recargas parciais (e quantas unidades o nível aumentará) e o que reduz o nível da bateria entre cada carga. Com esses dados, todas as noites calculo o nível mínimo de bateria necessário para sair de casa no dia seguinte, para que nunca caia abaixo do meu limite auto-imposto de duas unidades.

O que ainda não consegui dominar é o mesmo cálculo quando deixo a rotina estabelecida e tenho várias alternativas para fazer as coisas. Isso acontece, por exemplo, nos dias em que estou a caminho de outra cidade para a qual posso chegar de maneiras diferentes.

Na minha primeira abordagem ao problema, estou assumindo que quero me deslocar em um "tabuleiro de xadrez", do canto superior esquerdo para o canto inferior direito. Em cada "célula", posso cobrar do celular uma quantia específica ou não, e seu nível de carga diminui.

Desafio

Dada uma matriz FxC de números inteiros, produza a quantidade mínima de nível de bateria necessária para ir do canto superior esquerdo para o canto inferior direito sem que o nível de carga caia abaixo de 2 unidades.

Na matriz, um número positivo indica o quanto eu posso carregar o meu celular antes de continuar seguindo o meu caminho, enquanto um número negativo indica que não há tomadas e que a bateria do celular reduz seu nível de carga nessa quantia. É garantido que as quantidades nas células de origem e destino (canto superior esquerdo e inferior direito) sejam sempre 0 e que o restante dos valores (valor absoluto) não exceda 100.

Exemplo
:

[📱-1 11 1-1 1-1 1-1 1-1 1-1 1-1 11 1-1 1-1 11 11 1-1 10 0]

O caminho que preciso de menos bateria é:

[📱-1 11 1-1 1-1 1-1 1-1 1-1 1-1 11 1-1 1-1 11 11 1-1 10 0]

E a quantidade mínima de bateria que preciso é de 4

Notas

  • O início sempre será o canto superior esquerdo
  • O fim sempre será o canto inferior direito
  • Você não pode ir para uma célula pela qual você já passou. Exemplo: Uma vez na posição (0,1), você não pode ir para o ponto inicial (0,0)
  • O nível da bateria não pode (por qualquer motivo) ficar abaixo de 2
  • Você pode assumir que sempre haverá um começo e um fim
  • Você pode considerar as matrizes unidimensionais como multidimensionais, se precisar [1,2,3] == [[1,2,3]]
  • Pode haver vários caminhos corretos (carga mínima necessária)
  • Seu objetivo é produzir apenas o menor nível inicial de bateria necessário, não a rota
  • Você só pode ir na vertical e na horizontal (não na diagonal)

Casos de teste

[0, 0] => 2
[0, 1, 0] => 2
[0, -1, 0] => 3
[0, 15, -20, 5, 0] => 7
[[0, -3],[-5, 0]] => 5
[[0, -5, -9, 5], [-3, 5, 2, -2], [2, -4, -4, 0]] => 5
[[0, -1, 1, -1], [-1, -1, -1, -1], [-1, 1, -1, -1], [1, 1, -1, 0]] => 4

Eu esqueci o dia do desafio. Sandbox post
Luis felipe De jesus Munoz

Para qualquer um que se lembre: o desafio "The Hungry Moose" nunca saiu da caixa de areia, então isso não é bobagem.
Black Owl Kai

@BlackOwlKai Eu acho que os dois desafios são diferentes #
Luis felipe De jesus Munoz

11
O caminho ideal precisará ser movido para a esquerda ou para cima? Por exemplo[[0,1,-1],[-9,-9,1],[-9,1,-1],[-9,-1,-9],[-9,1,0]]
Kamil Drakari 15/02/19

11
@dana nenhum, há apenas 2 são 0scolocadas uma no canto superior esquerdo e o outro na parte inferior direita
Luis Felipe de Jesus Munoz

Respostas:


3

JavaScript (ES7),  162 156  154 bytes

m=>(M=g=(x,y,n,k)=>m.map((r,Y)=>[r[x+1]]+[m[y+1]]?r.map((v,X)=>r[1/v&&(x-X)**2+(y-Y)**2==1&&g(X,Y,u=v+n,k<u?k:u,r[X]=g),X]=v):M=M>k?M:k))(0,0,0)|M<0?2-M:2

Experimente online!

Comentado

m => (                          // m[] = input matrix
  M =                           // initialize M to a non-numeric value
  g = (x, y, n, k) =>           // g = recursive depth-first search function
    m.map((r, Y) =>             // for each row r[] at position Y in m[]:
      [r[x + 1]] +              //   if either r[x + 1]
      [m[y + 1]] ?              //   or m[y + 1] is defined:
        r.map((v, X) =>         //     for each value v at position X in r[]:
          r[                    //
            1 / v &&            //       if v is numeric
            (x - X) ** 2 +      //       and the squared Euclidean distance
            (y - Y) ** 2 == 1   //       between (x, y) and (X, Y) is 1:
            &&                  //
              g(                //         do a recursive call:
                X, Y,           //           with (X, Y)
                u = v + n,      //           with n = n + v
                k < u ? k : u,  //           with k = min(k, n + v)
                r[X] = g        //           set r[X] to a non-numeric value
              ),                //         end of recursive call
            X                   //       then restore r[X]
          ] = v                 //       to its initial value
        )                       //     end of inner map()
      :                         //   else (we've reached the bottom right corner):
        M = M > k ? M : k       //     update M to max(M, k)
    )                           // end of outer map()
)(0, 0, 0) |                    // initial call to g with x = y = n = 0 and k undefined
M < 0 ? 2 - M : 2               // return 2 - M if M is negative, or 2 otherwise

3

Python 2 , 208 202 bytes

lambda s:2-f(s)
def f(s,x=0,y=0):
 if x>-1<y<s[y:]>[]<s[y][x:]!="">s[y][x]:k=s[y][x];s[y][x]="";return k+min(0,max([len(s[y+1:]+s[y][x+1:])and f(eval(`s`),x+a/3-1,y+a%3-1)for a in 7,1,5,3]))
 return-9e9

Experimente online!


Python 2 , 217 211 bytes

i=input()
X,Y=len(i[0]),len(i)
s=[[0]*4+[i]];r=[]
for m,l,x,y,g in s:
 if X>x>-1<y<Y<"">g[y][x]:r+=[m]*(Y-y<2>X-x);l+=g[y][x];g[y][x]="";s+=[[min(m,l),l,x+a/3-1,y+a%3-1,eval(`g`)]for a in 7,1,5,3]
print 2-max(r)

Experimente online!


1

R , 224 220 217 213 210 bytes

f=function(x,m=rbind(0,cbind(0,x,0),0),i=2,j=2,p=F,k=c(1:-1,0,0,-1:1),b=Inf,`^`=min){m[i,j]=0
for(h in 1:4)b=b^'if'(all(c(R<-i+k[h],C<-j+k[h+4])>dim(x)),max(2,2-cumsum(p)^0),if(v<-m[R,C])b^f(x,m,R,C,c(p,v)))
b}

Experimente online!


1

C # (compilador interativo do Visual C #) , 242 bytes

a=>{int m=1<<31,n=~m;void g(int w,int x,int y,int z){for(int i=4,t,c,d,e;i-->0;)try{t=a[c=i<1?w-1:i<2?w+1:w,d=i>2?x-1:i>1?x+1:x];n=t==0&z<n?z:n;a[c,d]=m;e=y+t<2?2-y-t:0;if(t!=m)g(c,d,y+t+e,z+e);a[c,d]=t;}catch{}}a[0,0]=m;g(0,0,2,2);return n;}

Experimente online!

//a: input matrix
a=>{
  // m: marker for used cells
  // n: result, initialized to a huge value
  int m=1<<31,n=~m;
  // recursive function
  // w: 1st dim coordinate
  // x: 2nd dim coordinate
  // y: current charge level
  // z: initial charge for current path
  void g(int w,int x,int y,int z){
    // i: loop variable
    // t: temp holds overwritten value
    // c: adjacent 1st dim coordinate
    // d: adjacent 2nd dim coordinate
    // e: delta charge needed
    for(int i=4,t,c,d,e;i-->0;)
      // avoid index out of range errors
      // by using try/catch
      try{
        // determine neighbor
        // coordinates and save value
        t=a[c=i<1?w-1:i<2?w+1:w,
            d=i>2?x-1:i>1?x+1:x];
        // if we have found a 0, check if
        // initial charge is lower than the
        // lowest so far. save it if it is.
        n=t==0&z<n?z:n;
        // mark current cell used
        a[c,d]=m;
        // determine if we need to
        // increase the initial charge
        e=y+t<2?2-y-t:0;
        // make recursive call if current
        // cell was not previously in use
        if(t!=m)g(c,d,y+t+e,z+e);
        // restore current cell value
        a[c,d]=t;
      }catch{}
  }
  // mark starting cell used
  a[0,0]=m;
  // start the recursive function
  g(0,0,2,2);
  // return the result to the caller
  return n;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.