Выпуск#10: ITренировка — актуальные вопросы и задачи от ведущих компаний

    Ставшая уже традиционной, новая подборка вопросов и задач от SpiceIT.

    КДПВ

    Среди отобранных задач — вопросы и алогоритмические задачи, задаваемые соискателям на должность разработчика в Samsung. Предлагаем Вам попробовать решить их самостоятельно и оценить, готовы ли Вы подавать резюме в Samsung :)

    Вопросы


    1. 100 open/closed doors
      There are 100 doors in a row, all doors are initially closed. A person walks through all doors multiple times and toggle (if open then close, if close then open) them in following way:

      In first walk, the person toggles every door.

      In second walk, the person toggles every second door, i.e., 2nd, 4th, 6th, 8th, …

      In third walk, the person toggles every third door, i.e. 3rd, 6th, 9th, …

      ……….

      In 100th walk, the person toggles 100th door.

      Which doors are open in the end?
      Перевод
      В ряду находятся 100 закрытых дверей. Человек, проходит через двери множество раз, меняя их состояние (если открыта — закрывает, если закрыта — открывает), следующим образом:
      За первый проход посещает каждую дверь.
      За второй проход — каждую вторую дверь (2-ю, 4-ю, 6-ю, ...).
      За третий проход — каждую третью дверь.

      За сотый проход — сотую дверь.

      Какие двери в конце будут открытыми?
    2. Light bulbs and switches
      There is a room with a door (closed) and three light bulbs. Outside the room there are three switches, connected to the bulbs. You may manipulate the switches as you wish, but once you open the door you can’t change them. Identify each switch with its bulb.
      Перевод
      В комнате есть три лампы, дверь в комнату закрыта. Перед комнатой три выключателя, соединенные с лампами. Вы можете ставить выключатели в любое положение, но после того как откроете дверь — положение выключателей менять нельзя. Сопоставьте каждый выключатель с лампой.

      Подсказка
      (Прим. в задаче используется физика в т.ч.)

    Задачи


    1. Power of 2
      Write a program to test if a number is power of 2 or not in one line code.
      Перевод
      Напишите программу-однострочник, которая будет проверять, является ли число степенью двойки.
    2. Find an element in a sorted and rotated array
      An element in a sorted array can be found in O(log n) time via binary search. But suppose we rotate an ascending order sorted array at some pivot unknown to you beforehand. So for instance, 1 2 3 4 5 might become 3 4 5 1 2. Devise a way to find an element in the rotated array in O(log n) time.
      Перевод
      В отсортированном массиве элемент можно найти за O(log n) времени, используя двоичный поиск. Предположим, что мы повернули массив в произвольной точке, которая Вам заранее неизвестна. Так, например, 1 2 3 4 5 может стать 3 4 5 1 2. Предложите способ поиска элемента в таком массиве за O(log n) времени.
    3. Find a Number X whose sum with its digits is equal to N
      Given a positive number N. We need to find number(s) such that sum of digits of those numbers to themselves is equal to N. If no such number is possible print -1.
      N <= 1000000000.

      Examples:
      Input: N = 21
      Output: X = 15
      Explanation: X + its digit sum
      = 15 + 1 + 5
      = 21

      Input: N = 5
      Output: -1

      Input: N = 100000001
      Output: X = 99999937
      X = 100000000
      Перевод
      Дано положительное целое число N. Нам необходимо найти такое число (числа), чтобы сумма самого числа и его цифр равнялась N. Если таких чисел нет — вывести -1.

      Примеры:

      Вход: N = 21
      Выход: X = 15
      Объяснение: X + сумма его цифр
      = 15 + 1 + 5
      = 21

      Вход: N = 5
      Выход: -1

      Вход: N = 100000001
      Выход: X = 99999937
      X = 100000000

    Ответы будут даны в течение следующей недели — успейте решить. Удачи!

    Решения


    1. Вопрос 1
      Открытыми останутся двери: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100.

      Верный ответ дан в комментарии

    2. Вопрос 2
      Если включить одну лампочку, подождать пару минут, включить вторую и зайти в комнату, то первую лампочку можно будет определить по нагреву — она должна быть тёплой. Ответ был дан в комментарии комментарии.
      Тут также приведён замечательный вариант ответа.

    3. Задача 1
      Верные решения были предложены в комментариях. Исходный вариант на C++:
      #include<stdio.h>
      #include<stdbool.h>
      #include<math.h>
       
      /* Function to check if x is power of 2*/
      bool isPowerOfTwo(int n)
      {
         return (ceil(log2(n)) == floor(log2(n)));
      }
       
      // Driver program
      int main()
      {
          isPowerOfTwo(31)? printf("Yes\n"): printf("No\n");
          isPowerOfTwo(64)? printf("Yes\n"): printf("No\n");
          return 0;
      }


    4. Задача 2
      Исходное решение предполагает следующее — найти точку поворота, после чего попробовать найти элемент бинарным поиском сначала в первом подмассиве (до точки поворота), потом — во втором:

      
      /* Program to search an element in a sorted and pivoted array*/
      #include <stdio.h>
       
      int findPivot(int[], int, int);
      int binarySearch(int[], int, int, int);
       
      /* Searches an element key in a pivoted sorted array arrp[]
         of size n */
      int pivotedBinarySearch(int arr[], int n, int key)
      {
         int pivot = findPivot(arr, 0, n-1);
       
         // If we didn't find a pivot, then array is not rotated at all
         if (pivot == -1)
             return binarySearch(arr, 0, n-1, key);
       
         // If we found a pivot, then first compare with pivot and then
         // search in two subarrays around pivot
         if (arr[pivot] == key)
             return pivot;
         if (arr[0] <= key)
             return binarySearch(arr, 0, pivot-1, key);
         return binarySearch(arr, pivot+1, n-1, key);
      }
       
      /* Function to get pivot. For array 3, 4, 5, 6, 1, 2 it returns
         3 (index of 6) */
      int findPivot(int arr[], int low, int high)
      {
         // base cases
         if (high < low)  return -1;
         if (high == low) return low;
       
         int mid = (low + high)/2;   /*low + (high - low)/2;*/
         if (mid < high && arr[mid] > arr[mid + 1])
             return mid;
         if (mid > low && arr[mid] < arr[mid - 1])
             return (mid-1);
         if (arr[low] >= arr[mid])
             return findPivot(arr, low, mid-1);
         return findPivot(arr, mid + 1, high);
      }
       
      /* Standard Binary Search function*/
      int binarySearch(int arr[], int low, int high, int key)
      {
         if (high < low)
             return -1;
         int mid = (low + high)/2;  /*low + (high - low)/2;*/
         if (key == arr[mid])
             return mid;
         if (key > arr[mid])
             return binarySearch(arr, (mid + 1), high, key);
         return binarySearch(arr, low, (mid -1), key);
      }
       
      /* Driver program to check above functions */
      int main()
      {
         // Let us search 3 in below array
         int arr1[] = {5, 6, 7, 8, 9, 10, 1, 2, 3};
         int n = sizeof(arr1)/sizeof(arr1[0]);
         int key = 3;
         printf("Index: %dn", pivotedBinarySearch(arr1, n, key));
         return 0;
      }
      


    5. Задача 3
      Фактически, для числа X < = 1000000000, сумма цифр не превысит 100, следовательно мы можем написать следующий код:
      
      #include <cmath>
      #include <cstdlib>
      #include <iostream>
      #include <vector>
      using namespace std;
       
      // Computing the sum of digits of x
      int sumOfDigits(long int x)
      {
          int sum = 0;
          while (x > 0) {
              sum += x % 10;
              x /= 10;
          }
          return sum;
      }
       
      // Checks for 100 numbers on both left
      // and right side of the given number to
      // find such numbers X such that X + 
      // sumOfDigits(X) = N and updates the answer
      // vector accordingly
      void compute(vector<long int>& answer, long int n)
      {
          // Checking for all possibilities of 
          // the answer
          for (int i = 0; i <= 100; i++) {
       
              // Evaluating the value on the left 
              // side of the given number
              long int valueOnLeft = abs(n – i) +
                            sumOfDigits(abs(n – i));
       
              // Evaluating the value on the right
              // side of the given number
              long int valueOnRight = n + i + sumOfDigits(n + i);
       
              // Checking the condition of equality 
              // on both sides of the given number N 
              // and updating the answer vector
              if (valueOnLeft == n)
                  answer.push_back(abs(n – i));
              if (valueOnRight == n)
                  answer.push_back(n + i);
          }
      }
       
      // Driver Function
      int main()
      {    
          long int N = 100000001;
       
          vector<long int> answer;
          compute(answer, N);
       
          // If no solution exists, print -1
          if (answer.size() == 0)
              cout << -1;
          else {
       
              // If one or more solutions are possible,
              // printing them!
              for (auto it = answer.begin(); it != answer.end(); ++it)
                  cout << "X = " << (*it) << endl;
          }
          return 0;
      }
      


    Spice IT Recruitment
    82.39
    ИТ специализированное кадровое агентство
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 34

      +2
      Первая задача
      Дверь будет менять состояние, если её номер (D) нацело делится на номер прохода. Все такие номера проходов можно получить, если разложить номер двери на простые множители (p1...pk) и взять все различные их комбинации
      D = p1n1 × p2n2 ×… × pknk
      Количество различных комбинаций этих множителей даст количество проходов, на которых дверь сменит состояние. Его можно получить как
      N = (n1 + 1) × (n2 + 1) ×… × (nk + 1)
      Для того, чтобы дверь в конце осталась открытой она должна сменить своё состояние нечётное количество раз. Такое возможно только если все множители (ni + 1) будут нечётными, то есть все ni будут чётными.
      Но, раз все ni — чётные, то мы можем записать изначальное разложение как
      D = (p1n1/2)2 × (p2n2/2)2 ×… × (pknk/2)2 = (p1n1/2 × p2n2/2 ×… × pknk/2)2
      Таким образом, открытыми останутся только двери, чьи номера представляют собой квадраты целых чисел, то есть 1, 4, 9, 16, 25, 36, 49, 64, 81, 100.
        0
        На самом деле дверь номер 8 тоже в итоге будет открыта, но она не является квадратом целого числа
          0
          Давайте посчитаем: проход 1 — открыта, 2 — закрыта, 4 — открыта, 8 — закрыта. Какие ещё проходы меняют состояние этой двери?
        0
        Power of 2
        public bool IsPowerOfTwo(int Number) { return ((Number & 1) == 0) ? IsPowerOfTwo(Number >> 1) : Number == 1; }


        Find an element in a sorted and rotated array
        
                static int SearchInLeftPart(int[] Arr, int Number)
                {
                    int BreakPointMin = Arr[Arr.Length - 1];
                    int BreakPointMax = Arr[0];
                    int Left = 0;
                    int Right = Arr.Length - 1;
                    int Med;
                    while (Left < Right)
                    {
                        Med = (Left + Right) / 2;
                        if (Arr[Med] == Number) return Med;
                        if (Arr[Med] <= BreakPointMin)
                        {
                            Right = Med - 1;
                            continue;
                        }
                        if (Arr[Med] > Number)
                        {
                            Right = Med - 1;
                        }
                        else
                        {
                            Left = Med + 1;
                        }
                    }
                    if (Arr[Left] == Number) return Left;
                    return -1;
                }
                static int SearchInRightPart(int[] Arr, int Number)
                {
                    int BreakPointMin = Arr[Arr.Length - 1];
                    int BreakPointMax = Arr[0];
                    int Left = 0;
                    int Right = Arr.Length - 1;
                    int Med;
                    while (Left < Right)
                    {
                        Med = (Left + Right) / 2;
                        if (Arr[Med] == Number) return Med;
                        if (Arr[Med] >= BreakPointMax)
                        {
                            Left = Med + 1;
                            continue;
                        }
                        if (Arr[Med] > Number)
                        {
                            Right = Med - 1;
                        }
                        else
                        {
                            Left = Med + 1;
                        }
                    }
                    if (Arr[Left] == Number) return Left;
                    return -1;
                }
        
                static public int SearchInArr(int[] Arr, int Number)
                {
                    int BreakPointMin = Arr[Arr.Length - 1];
                    int BreakPointMax = Arr[0];
                    if (BreakPointMin > BreakPointMax) return Array.BinarySearch(Arr, Number);
        
                    if (Number > BreakPointMin && Number < BreakPointMax) return -1;
        
                    if (Number <= BreakPointMin) return SearchInRightPart(Arr, Number);
                    else return SearchInLeftPart(Arr, Number);
                }


          0
          Find a Number X whose sum with its digits is equal to N
          Тут идет простой перебор, но перебор начинается с числа N-((порядок числа N)*9) и идет до N-1
                  static int[] GetNumbers(int N)
                  {
                      List<int> res = new List<int>();
                      int Order = 1;
                      int tmp = N;
                      while (tmp/10 != 0)
                      {
                          Order++;
                          tmp /= 10;
                      }
                      int start = N - Order * 9;
                      if (start < 0) start = 0;
                      for (int i = start; i < N; i++)
                      {
                          if (i+ GetSumOfDigits(i) == N)
                          {
                              res.Add(i);
                          }
                      }
                      return res.ToArray();
                  }
                  static int GetSumOfDigits(int N)
                  {
                      int res = 0;
                      while (N / 10 != 0)
                      {
                          res += N%10;
                          N /= 10;
                      }
                      res += N;
                      return res;
                  }
          

            0
            Я думаю, что про power of 2 скорее было
            это.
            x > 0 && ((x — 1) & x) == 0
            0
            По первому вопросу: посещение двери равно её порядковому номеру.
            По второму вопросу: так как там лампы, можно попытаться определить по нагреву — горячая, теплая, бе нагрева — только причем тут программирование…
            По первой задаче: в одну строку можно посчитать количество бит в числе — если равно 1 то степень двойки.
            По второй задаче: глядя на первый и последний элементы возможно можно узнать точку поворота.
              0
              По второй задаче: глядя на первый и последний элементы возможно можно узнать точку поворота.


              Однако, тоже за логарифмическое время (см. задачу за прошлую неделю). А потом второй проход по одному из двух подмассивов. Если сохранить значения из первого прохода, можно, наверное, немного сэкономить на втором.
                0
                Имхо, можно и за один проход. Обычным бинарным поиском, только при делении определяете какой диапазон корректен (не содержит излома), если число в нем — дальше обычный бинарный поиск, иначе берете другой диапазон не проверяя его.
                0
                По второму вопросу: так как там лампы, можно попытаться определить по нагреву — горячая, теплая, бе нагрева — только причем тут программирование…
                В этом случае, условие задачи не полное, т.к. не исключает вариант, что лампы висят на высоте 5 метров и нет никаких подручных средств, чтобы их достать.
                  +1
                  А условие и так не полное. Сказано, что выключатели подключены к лампам, но не сказано, подключен ли каждый выключатель только к одной лампе, подключен ли к каждой лампе только один выключатель, подано ли питание к лампам через выключатели, можно ли закрыть дверь и снова переключить выключатели, и т.д, и т.п., и пр.
                  0
                  По первому вопросу: посещение двери равно её порядковому номеру.

                  Сколько раз посещали двери под номерами 3,5,7,11,13....?
                  +2
                  Power of 2
                  bool function isPowerOf2(int number) { return !(number & (number - 1)); }

                    0
                    Чутка не хватает.
                    Проверяем
                      0
                      Согласен, ноль не учёл. Хотя,… 0 = 2−∞
                        0
                        Отнюдь! У вас тут должен быть предел, т.к ∞ — не число.
                    +2
                    IMHO, на задачу о лампочке лучше всего ответил (бы) Фейнман blogs.msdn.microsoft.com/ruericlippert/2011/02/28/983

                    TL;DR
                    И почему решение, к которому вы меня подталкиваете, основывается на недокументированных и ненадежных побочных явлениях? Неужели ваша команда пишет код, корректность которого основывается на недокументированных и ненадежных взаимосвязях, которые могут на порядок отличаться в зависимости от деталей реализации?
                      0
                      Что-то сегодня простые задачи.
                      Power of 2
                      v && !(v & (v — 1))

                      Find an element in a sorted and rotated array
                      Сначала бинарным поиском найдем излом, затем бинарный поиск в нужной части.

                      Find a Number X whose sum with its digits is equal to N
                      Разница X и N не более 81, значит проще всего от N проверять вниз ближайшие 81 число.
                        0
                        Заголовок спойлера
                        1 вопрос. Открытыми будут только двери, чьи номера образуют квадрат, т.е. 1,4,9,16,25,...100
                        2 вопрос. Баян, и вообще вопрос многими считается не корректным.
                        1. Задача. Отнимаем от числа 1, и побитово умножаем с исходным числом.
                        2. Задача. Опять повороты массивов. Смысл давать похожие задачи между 2-мя выпусками?
                        Над последней задачей ещё думаю.
                          0
                          Ради интереса - чуть менее тривиальное решение последней задачи
                          f 0 a 0 = [a]
                          f 0 _ _ = []
                          f d a n | c >  9    = []
                                  | c == 0    = [c] >>= f'
                                  | otherwise = [c, c-1] >>= f' where
                              d1 = d + 1
                              c  = div n d1
                              d' = div d 10
                              f' v = f d' (v:a) (n-v*d1)
                          
                          toi = foldr (\x a -> a*10 + x) 0
                          
                          g n = map toi . f (10^(length $ show n)) [] $ n
                          
                          main = do
                              mapM (\x -> putStrLn $ show x ++ "   " ++ show (g x)) [10000000000000..10000000000010]
                            0
                            Что это за язык?
                              +1

                              Должно быть, Эльфийский

                                +1
                                Хотя не, вот кажется ключ к разгадке

                                image

                            0
                            del
                              0
                              Порция унижения. 1й вопрос — даже готовое решение с трудом понимаю. Это тест на мат эрудию? Или что, действительно вот так приходят и выкладывают решение в приятной беседе?
                                0

                                Это известный факт, что только у полных квадратов нечётное число делителей. Доказать тоже не сложно (до корня и после всегда поровну. Значит есть сам корень). Все длинные рассуждения можно не писать.

                                0
                                Find a Number X whose sum with its digits is equal to N

                                def f(N):
                                    res = []
                                    for x in range(max(N - 9 * len(str(N)), 1), N):
                                        if x + sum(map(int, str(x))) == N:
                                            res.append(x)
                                    print(f'N = {N}, X : {res or [-1]}')
                                
                                
                                f(21)
                                f(5)
                                f(100000001)
                                

                                вывод
                                N = 21, X : [15]
                                N = 5, X : [-1]
                                N = 100000001, X : [99999937, 100000000]
                                  0

                                  Имхо, получается только первый вопрос более-менее нетривиален, учитывая что ответ надо дать не кодом а в результате устных рассуждений. Ну и третья задача допускает алгоритм, немного интереснее очевидного (опубликовал выше).
                                  Про лампочки — баян (к тому же спорный), про степень двойки — трижды баян, но далеко не все языки дают доступ к битовому представлению чисел, поэтому альтернативный однострочник


                                  на неземном волшебном
                                  f n = n==1 || r==0 && f q where (q,r) = quotRem n 2

                                  про сортированный массив — тоже очевидно.


                                  Но для школьников старших классов вполне подходящие задачки на факультатив.

                                    0

                                    Не знаю, была ли подобная задача тут или нет.


                                    В комнате находится шахматная доска, на каждой клетке которой лежит по одной монете.
                                    Первый участник заходит в комнату и узнает "ключевую" клетку.
                                    Он может перевернуть не более одной любой монеты.
                                    Задача второго участника найти "ключевую" клетку.


                                    ПС

                                    Попытка передать информацию с помощью сдвига монеты к краю, поворота, царапин и т.п. недопустима.

                                    0
                                    прячу ответы
                                    1) остануться открытыми полные квадраты и 1. 1,4,16,64,9,81,25,36,49,100
                                    2) уже видел когда-то. Один выключатель нужно включить на время и выключить, чтобы найти соответствие по температуре.
                                    1. if (sumarray(char a[] = (string(binary(x)))) == 1) then println(«power of two!»)
                                    2. ищем пивот как в прошлонедельной задаче. Дальше переопределяем начало кольца этим пивотом. Всё, массив вернули в исходное состояние, для которого уже было готовое решение за такое время.
                                    3. Положим, на входе 7 значное число. Максимум, который могут дать цифры в сумме — это 6 девяток и первая цифра числа — 1. Отступим от числа на 6*9+первая_цифра-1, и переберём небольшое число вариантов. Количество проверяемых чисел — пропорционален логарифму от входного числа. Проверка суммы цифр так же пропорциональна длине чисел, так что всего получаем быстроту O((log(N))^2).
                                      0
                                      Дополнение про двери: интересно, что в задаче упомянуто, что двери стоят в ряд, а не в кольцо. В этом смысле задача напоминает задачу о заключённом, и мы должны следить за положением человека — каждый раз доходя до конца ряда он будет вынужден проходить его в противоположном направлении. То есть каждую дверь он открыл, затем, идя в обратную сторону, закрыл каждую вторую — и это все нечётные двери, а не чётные. Точно так же в последнюю ходку он меняет состояние 1 двери, а не последней. Открытыми останутся 1,2,3,4,8,9,16,18,25,29,32,36,49,50,51,64,69,72,81,83,93,98,99,100.
                                      Глядя на этот ряд у меня возникает два вопроса: существует ли аналитический способ получить его? И почему он всё ещё содержит весь правильный ряд, как если бы мы делали прогоны в одну сторону? Если поменять количество дверей (я пробовал 101, чётные, нечйтные, полные квадраты и простые) то можно избавится от последней сотни, но на дальней перспективе, уже к 81, все меньшие полные квадраты сохраняются… Так странно… Очень не похоже на совпадение.
                                        0
                                        положение двери изменяется число раз равное количеству делителей числа включая единицу и само число, и соответственно если количество делителей нечётное, состояние двери изменится.
                                        Но это если бы чувак ходил каждый раз в одном направлении, но тут явно имеется в виду что он ходит туда — обратно так что я сразу так не могу придумать формулу
                                      0
                                      Я наверное в своей прошлой работе перерешала задач, что сейчас уже не хочу решать ничего из этого. Тем более на работе с такими задачами каждый день процентов 90 находящихся здесь не сталкиваются.
                                      Но решить задачу это не показатель. На их решения обычно натаскивают. Не тривиальных задач довольно мало. Остальные решаются по известным алгоритмам. Поэтому основная проблема — отнести задачу к соответствующему типу задач.
                                      P.S. Утверждаю это как бывший преподаватель высшей математики, готовила и к олимпиадным задачам и к ЕГЭ.

                                      Only users with full accounts can post comments. Log in, please.