Google Kickstart于2018年第A轮出现“偶数”问题

时间:2019-04-04 11:11:32

标签: c# algorithm

我目前正在参加Google Kickstart比赛的练习,目前正在Even Digits problem from Round A of 2018上工作。

我创建了以下算法,当我对其进行测试时,它的效果很好。但是问题是,当我将其提交到平台并按下“尝试”按钮时,它表明我的输出不正确

我尝试使用更大或更复杂的数字对其进行测试,但我只是找不到情况

  

问题描述:

     

Supervin有一个独特的计算器。该计算器只有一个显示屏,一个加号按钮和一个减号按钮。当前,整数 N 显示在计算器显示屏上。
  按加号按钮会将计算器显示屏上显示的当前数字增加1。类似地,按减号按钮会将计算器显示屏上显示的当前数字减少1。计算器不显示任何前导零。例如,如果 100 显示在计算器显示屏上,则按下减号按钮一次将使计算器显示 99
  Supervin不喜欢奇数,因为他认为奇数是“奇数”。因此,他只想使用计算器按钮来显示一个仅用偶数位表示的整数。由于计算器有点旧并且按钮难以按下,因此他希望使用最少的按钮按下次数。
  请帮助Supervin确定按下按钮的最小次数,以使计算器显示没有奇数的整数。
  输入
  输入的第一行给出测试用例的数量, T 。接下来是 T 测试用例。   每行以包含整数 N 的一行开头:   Supervin计算器上最初显示的整数。

这是我的代码:

public static void Main(string[] args)
{
  var SCount = Console.ReadLine();
  long Count = Convert.ToInt64(SCount);

  for (long i = 0; i < Count; i++)
  {
    var val = Console.ReadLine();
    long l = Convert.ToInt64(val);

    Console.WriteLine("Case #{0}: {1}", i + 1, Slover4(l));
  }
}

public static long Slover4(double N)
{
  char[] odds = { '1', '3', '5', '7', '9' };

  double presses_p = 0;
  double PN = N;
  double presses_n = 0;
  double NN = N;

  double pdegits = -1;
  for (int i = PN.ToString().Length - 1; i >= 0; i--)
  {
    pdegits += 1;

    //2110
    //2018 EVEN EVEN (ODD EVEN)  ---->
    //11   ODD OOD               <----
    //1    ODD                   ---->
    //42   EVEN EVEN             XXXXX 6969 1 | 6970 30 | 7000 -200 | 6800

    #region Positives
    if (i > 0 && odds.Contains(PN.ToString()[i]) &&
        odds.Contains(PN.ToString()[i - 1])) // ODD - ODD 
    {
      var val = int.Parse(string.Concat(PN.ToString()[i - 1], PN.ToString()[i]));
      var lv = int.Parse(PN.ToString()[i].ToString());
      //15 17  19
      //5  3   1
      presses_p += (5 - (lv - 5)) * Math.Pow(10, pdegits);
      PN += (5 - (lv - 5)) * Math.Pow(10, pdegits);
    }
    else if (i != 0 &&
             !odds.Contains(PN.ToString()[i - 1]) &&
             odds.Contains(PN.ToString()[i])) // EVEN - ODD 
    {
      presses_p += Math.Pow(10, pdegits);
      PN += Math.Pow(10, pdegits);
    }
    else if (i != 0 && 
             odds.Contains(PN.ToString()[i - 1])) // ODD - EVEN
    {
      var val = int.Parse(string.Concat(PN.ToString()[i - 1], PN.ToString()[i]));
      var lv = int.Parse(PN.ToString()[i].ToString());

      //10 12 14 16 18
      //10  8  6  4  2  ->

      //10 12 14|
      //2 4  6 |
      presses_p += (10 - lv) * Math.Pow(10, pdegits);
      PN += (10 - lv) * Math.Pow(10, pdegits);
    }
    else if (i == 0 && 
             odds.Contains(PN.ToString()[i])) // ODD Only
    {
      presses_p += Math.Pow(10, pdegits);
      PN += Math.Pow(10, pdegits);
    }
    #endregion

    #region Negatives 

    if (i > 0 && 
        odds.Contains(NN.ToString()[i]) && 
        odds.Contains(NN.ToString()[i - 1])) // ODD - ODD 
    {
      var val = int.Parse(string.Concat(NN.ToString()[i - 1], NN.ToString()[i]));
      var lv = int.Parse(NN.ToString()[i].ToString());
      //11 13 15 17 19
      //3  5  7  9  11
      presses_n += (3 + (lv - 1)) * Math.Pow(10, pdegits);
      NN -= (3 + (lv - 1)) * Math.Pow(10, pdegits);
    }
    else if (i != 0 &&
             !odds.Contains(NN.ToString()[i - 1]) &&
             odds.Contains(NN.ToString()[i])) // EVEN - ODD 
    {
      presses_n += Math.Pow(10, pdegits);
      NN -= Math.Pow(10, pdegits);
    }
    else if (i != 0 &&
             odds.Contains(NN.ToString()[i - 1])) // ODD - EVEN
    {
      var val = int.Parse(string.Concat(NN.ToString()[i - 1], NN.ToString()[i]));
      var lv = int.Parse(NN.ToString()[i].ToString());

      //10 12 14 16 18     
      //2  4  6  8  10  <-

      presses_n += (2 + lv) * Math.Pow(10, pdegits);
      NN -= (2 + lv) * Math.Pow(10, pdegits);
    }
    else if (i == 0 &&
             odds.Contains(NN.ToString()[i])) // ODD Only
    {
      presses_n += Math.Pow(10, pdegits);
      NN -= Math.Pow(10, pdegits);
    }
    #endregion
  }

  //$"P:{presses_p} - N - {presses_n}";
  return presses_p < presses_n ? (long)presses_p : (long)presses_n;
}

1 个答案:

答案 0 :(得分:4)

好吧,让我们从退化的案例开始:

  1. 如果我们给我们所有偶数个数字(例如2048),我们将返回0
  2. 如果仅是最后一位数字是奇数(例如64087),我们返回1

现在让left是最左边的奇数(leftDigit)的索引,例如

 2480032581
      ^
      left = 5 (since 2, 4, 8, 0, 0 are even)
      leftDigit = 3

我们可以将初始号码转换为任意数字(通过按-按钮)

 2480028888

或(按 + 按钮)进入

 2480040000

最后,我们可以比较这两种可能性,并采用需要更少印刷机的一种方法:

 "-"  wants 2480032581 - 2480028888 == 3693 presses
 "+"  wants 2480040000 - 2480032581 == 7419 presses

对于给定的数字,按-是更好的策略,因此我们返回3693。 请注意,如果leftDigit9,我们将坚持按"-"进行操作(并忽略+策略)。

C#代码:

private static long Solution(string value) {
  int left = -1;

  for (int i = 0; i < value.Length; ++i) {
    if ((value[i] - '0') % 2 != 0) {
      left = i;

      break;
    }
  }

  if (left < 0)
    return 0;                 // All even digits number 
  else if (left == value.Length - 1)
    return 1;                 // The very last digit is the only odd one

  long initial = long.Parse(value.Substring(left));
  int leftDigit = value[left] - '0';

  if (leftDigit == 9)
    return initial - long.Parse(new string('8', value.Length - left));

  long plus = 
    long.Parse((leftDigit + 1).ToString() + new string('0', value.Length - left - 1)) - 
    initial;

  long minus = initial - 
    long.Parse((leftDigit - 1).ToString() + new string('8', value.Length - left - 1));

  return plus < minus ? plus : minus;
}

演示:

  string[] tests = new[] {
    "42",
    "11",
    "1",
    "2018"
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,6} -> {Solution(test),3}"));

结果:

    42 ->   0
    11 ->   3
     1 ->   1
  2018 ->   2