Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
1 / 1 / 2
Регистрация: 25.08.2012
Сообщений: 108

Программирование без использования условных конструкций

27.11.2016, 14:42. Показов 2860. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ребят, задали на собеседовании такую задачку:
Есть метод с тремя параметрами - bool flag, del1 a,del1 b.
Необходимо реализовать этот метод так, что бы в зависимости от флага вызывался нужный делегат.
Все ничего, вот только надо сделать так, что бы в реализации не было логических операций(if,else,case...).
Была подсказка использовать hash-совместимые контейнеры типа dictionary. Но я так и не придумал верного решения.
Может кто знает как это должно выглядеть?
Спасибо.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.11.2016, 14:42
Ответы с готовыми решениями:

Изучение условных и циклических конструкций
нужно сделать программу с подробным пояснением (если не лень)как и что откуда берется. По теме Изучение условных и циклических...

Обнулить строки, у которых наименьший элемент больше 0.5 (без использования циклов и условных операторов)
Написать функцию на языке MATLAB, которая без использования циклов и условных операторов: Принимает в качестве параметра прямоугольную...

Написать программу подсчета в тексте количества условных конструкций
В файле хранится работающая программа ЯП Pascal. Написать программу подсчета в тексте количества. Условных конструкций if ... then ......

19
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
27.11.2016, 14:57
Лучший ответ Сообщение было отмечено Olejan_one как решение

Решение

Цитата Сообщение от Olejan_one Посмотреть сообщение
Может кто знает как это должно выглядеть?
Примерно так:
C#
1
2
3
4
5
6
7
8
var actions = new Dictionary<bool, del1>
{
   [false] = a,
   [true]  = b
};
 
bool flag = ...;
actions[flag]();
1
 Аватар для Пaтрик
442 / 410 / 132
Регистрация: 21.01.2012
Сообщений: 976
27.11.2016, 14:57
Лучший ответ Сообщение было отмечено Olejan_one как решение

Решение

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;
using System.Reflection;
 
namespace Thread1861494
{
    internal class Program
    {
        private static readonly Dictionary<bool, Action<int, int>> Handlers;
 
        private static void Action1(int a, int b)
        {
            Console.WriteLine(MethodInfo.GetCurrentMethod().Name);
        }
 
        private static void Action2(int a, int b)
        {
            Console.WriteLine(MethodInfo.GetCurrentMethod().Name);
        }
 
        static Program()
        {
            Handlers = new Dictionary<bool, Action<int, int>>
            {
                { false, Action1 },
                { true, Action2 }
            };
        }
 
        private static void Foo(bool f, int a, int b)
        {
            Handlers[f](a, b);
        }
 
        private static void Main(string[] args)
        {
            Foo(false, 1, 2);
            Foo(true, 1, 2);
            Console.ReadLine();
        }
    }
}
1
1 / 1 / 2
Регистрация: 25.08.2012
Сообщений: 108
27.11.2016, 15:17  [ТС]
Ох, спасибо ребят, все оказывается намного легче чем я думал. Просто никогда с дикшенари не работал еще. Еще небольшой вопросик по поводу хештейбл и дикшенари. Где можно почитать удобную информацию о этих коллекциях? В гугле искал, но то что нашел не очень воспринимается. Может есть книги, где доступно описано хеширование и использование этих коллекций? Спасибо.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
28.11.2016, 10:45
Olejan_one, в принципе, если без использования if`ов, то можно было и так сделать:
C#
1
(flag ? a : b)();
Само-собой, если целью задания было выяснить умеет ли новобранец пользоваться словарями, этот способ не проканает.
0
Эксперт .NET
 Аватар для Usaga
14145 / 9374 / 1350
Регистрация: 21.01.2016
Сообщений: 35,307
28.11.2016, 10:48
Цитата Сообщение от Olejan_one Посмотреть сообщение
Просто никогда с дикшенари не работал еще.
Если ты с коллекциями толком работать не умеешь, то про собеседования думать рановато.
3
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
28.11.2016, 10:50
Цитата Сообщение от Olejan_one Посмотреть сообщение
Где можно почитать удобную информацию о этих коллекциях?
Например, тут
0
1 / 1 / 2
Регистрация: 25.08.2012
Сообщений: 108
28.11.2016, 15:17  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
Например, тут
Спасибо, статью прочитал. Неплохо написано, но всё же мне все равно не очень ясно несколько вещей:
1. Собственно, насколько я понял суть хешей в контексте коллекций состоит в том, что можно быстро найти нужный элемент. Мне не очень ясен сам алгоритм поиска -
Поправьте меня если не правильно описываю:
а) Класс, который реализует ключи должен переопределять метод GetHashCode().
б) Соответственно получается что например при поиске ключа "Саша" словарь хеширует строку "Саша" и получает хеш, к примеру 122345.
в) дальше начинается перечисление ключей и вызов метода GetHashCode() на каждом элементе для сравнения с хешем 122345?

По моему результат будет долгим.
Или я что то не так понял.

2. Мне не понятно что такое "емкость словаря или Capacity". Я привык к свойству Count. Соответственно сколько элементов добавилось, такая и емкость коллекции. Добавилось 5 элементов - коллекция динамически возрастает на это количество. А что такое емкость словаря не пойму, и почему она может отличаться от количества элементов, которые находятся в словаре.

3. В случае возникновения коллизии есть 2 метода реализации:
а) Метод линейного поиска - объекты, ключи которых образуют одинаковый хеш преобразуются в линейный односвязный список, каждый элемент в котором содержит адрес следующего элемента в списке. У меня вопрос - у нас есть значение "Маша", образующее хеш 65478. В словаре есть еще 50 элементов, которые возвращают такой же как и у "Маши" хеш - 65478. Соответственно у нас по значению хеша 65478 - появляется линейный список из 51 элемента. Как в этом случае происходит поиск по этому линейному списку? Как нам найти значение "Маша"? На этом этапе словарь использует уже не значение хеша а сам ключ "Маша" и сравнивает его с каждым ключом списка?

б) Метод открытой адресации: тут почти все понятно. Элементы с одинаковым хешем помещаются не в список, а друг за другом по словарю, в первую пустую позицию после элемента с которым совпал хеш. Вопрос: в каждой статье пишут, что в этом случае элементы должны распределяться равномерно по словарю. Это как? Допустим есть элемент "Саша" с хешем 45678 и элемент "Маша" с таким же хешем 45678. В итоге мы вставляем Сашу в ячейку под номером 45678. Далее следующая ячейка под номером 45679 уже занята другим элементом. В итоге Машу мы вставляем в следующую свободную ячейку - к примеру 45680.
Что в итоге получилось:
45678 - Саша
45679 - Коля
45680 - Маша

В чем заключается равномерность данного словаря?

Спасибо. Буду благодарен за любой ответ.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
28.11.2016, 15:29
Цитата Сообщение от Olejan_one Посмотреть сообщение
По моему результат будет долгим.
я внутрь исходников мелкософта не лазил и точно ответить не смогу. Подозреваю, что именно так и происходит. Не думаю, что человеческими органами чувств будет замечен спад производительности, но использовать в качестве ключа тип String я бы вообще не рекомендовал.

Цитата Сообщение от Olejan_one Посмотреть сообщение
А что такое емкость словаря не пойму
Грубо-говоря - объём памяти, зарезервированный под словарь, при добавлении элемента свыше этого количества происходит пересоздание коллекции, с соответствующими накладными расходами.

Цитата Сообщение от Olejan_one Посмотреть сообщение
В случае возникновения коллизии есть 2 метода реализации
Вот тут не подскажу. Ищи и разбирай исходники.
1
1 / 1 / 2
Регистрация: 25.08.2012
Сообщений: 108
28.11.2016, 15:51  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
Грубо-говоря - объём памяти, зарезервированный под словарь, при добавлении элемента свыше этого количества происходит пересоздание коллекции, с соответствующими накладными расходами.
Ага, ну так уже яснее. Но все же я ж не буду каждый раз вычислять обьем данных, он может каждый раз быть разным. Наверно это хорошо когда размер данных близок к постоянному. Т.е. когда я заранее могу его знать примерно. Ну да ладно, разберусь с этим. Спасибо большое.

Добавлено через 3 минуты
Цитата Сообщение от aquaMakc Посмотреть сообщение
1
(flag ? a : b)();
Тернарный оператор - это условная конструкция. А надо без неё. Ну варианты уже есть, и этого хватило. Dictionary решает задачу.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
28.11.2016, 15:52
Цитата Сообщение от Olejan_one Посмотреть сообщение
Тернарный оператор - это условная конструкция. А надо без неё.
Я сначала прочитал задачу как "...без использования if..."
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
28.11.2016, 17:50
Цитата Сообщение от Olejan_one Посмотреть сообщение
Класс, который реализует ключи должен переопределять метод GetHashCode().
Не только.
Так же он должен переопределить Equals и желательно (но не обязательно) реализовать интерфейс IEquatable.
Потому что если два объекта равны через метод Equals, то они должны генерировать и одинаковый хэш.

Цитата Сообщение от Olejan_one Посмотреть сообщение
в) дальше начинается перечисление ключей и вызов метода GetHashCode() на каждом элементе для сравнения с хешем 122345?
Нет.
Словарь группирует все добавляемые значения по их хэшу. Когда вы делаете поиск, то высчитывается хэш только того ключа, который вы передали для поиска — чтобы определить группу, в которой должно находиться искомое значение. Дальше идет линейный поиск по всем элементам в этой группе.

Цитата Сообщение от Olejan_one Посмотреть сообщение
Мне не понятно что такое "емкость словаря или Capacity".
Емкость — это количество элементов, которое может быть добавлено в коллекцию до того, как она заполнится и придется выделять память под новые элементы.

Цитата Сообщение от Olejan_one Посмотреть сообщение
сколько элементов добавилось, такая и емкость коллекции. Добавилось 5 элементов - коллекция динамически возрастает на это количество.
И с добавлением каждого элемента вам придется копировать все уже до этого добавленные для того, чтобы увеличить размер.
Это будет очень накладно и медленно — попробуйте для развлечения реализовать свой динамический массив MyList<T> с предложенным вами механизмом.
Чтобы не копировать весь массив при каждом добавлении, динамические коллекции, которые в качестве детали реализации используют обычный массив, выделяют память с запасом. Count показывает 5 элементов, а массив в кишках коллекции выделен на 8 элементов — это и есть Capacity.

Вот вам код для демонстрации:
C#
1
2
3
4
5
6
var list = new List<int>();
for (int i = 0; i < 100; i++)
{
   list.Add(i);
   Console.WriteLine($"Count = {list.Count}; Capacity = {list.Capacity}");
}
Цитата Сообщение от Olejan_one Посмотреть сообщение
Как в этом случае происходит поиск по этому линейному списку?
Последовательно, вызывая Equals на каждом элементе до тех пор, пока один из них не вернет true.
Тот, который вернет, и будет считаться найденным элементом.

Цитата Сообщение от Olejan_one Посмотреть сообщение
В чем заключается равномерность данного словаря?
Данного — ни в чем, потому что равномерности там нет
"Равномерность" — это, грубо говоря, разбиение массива на промежутки, где каждый промежуток назначается определенному хэшу: скажем, с первого по десятый элементы массива будут хранить объекты с хэшем 45678. С одиннадцатого по двадцатый — зарезервированы для элементов с хэшем 45679 и т.д.

Кстати, к слову о емкости коллекции: в приведенном примере словарь для хранения использует массив из двадцати элементов — это его емкость, а храниться в нем могут на данный момент только Саша и Маша: Count == 2.
0
 Аватар для m0nax
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
28.11.2016, 20:16
Цитата Сообщение от aquaMakc Посмотреть сообщение
я внутрь исходников мелкософта не лазил и точно ответить не смогу. Подозреваю, что именно так и происходит. Не думаю, что человеческими органами чувств будет замечен спад производительности, но использовать в качестве ключа тип String я бы вообще не рекомендовал.
там хранится хеш этих строк, ничего потом не считается больше
а вообще словари очень быстрые, собственно нет ничего быстрей поиска по ключу в словаре, каким-то образом даже двоичный поиск сдает позиции против обычного Dictionary(я раньше думал что там и есть двоичный поиск), возможно как раз группировки имеют в этому отношение
даже если хранить там сотни тысяч записей поиск укладывается в несколько миллисекунд, какими там органами измерить )
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
28.11.2016, 22:56
Цитата Сообщение от m0nax Посмотреть сообщение
даже если хранить там сотни тысяч записей поиск укладывается в несколько миллисекунд, какими там органами измерит
скорость - это хорошо, но тип String слишком большое поле для возможных ошибок оставляет, особенно, если значение вводится пользователем. Можно, конечно, использовать строковые константы в качестве ключа, но лучше всё-таки более однозначные типы применять. Вот это я хотел сказать.
0
1 / 1 / 2
Регистрация: 25.08.2012
Сообщений: 108
28.11.2016, 23:45  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Нет.
Словарь группирует все добавляемые значения по их хэшу. Когда вы делаете поиск, то высчитывается хэш только того ключа, который вы передали для поиска — чтобы определить группу, в которой должно находиться искомое значение. Дальше идет линейный поиск по всем элементам в этой группе.
Здесь не очень понятно - Вы написали "что бы определить группу...". Как словарь ищет эту группу?
К примеру есть такой словарь mydictionary:
1000-Маша
1001-Саша->1001-Коля
1002-Вася
1003-Петя

1. Для того что бы найти обьект "Коля" мы берем метод - mydictionary.ContainsKey("Коля");
2. В этот момент словарь берет этот передаваемый параметр "Коля" высчитывает хеш для этого значения. Результат - 1001.
3. Затем как Вы сказали словарь должен найти группу, в которой находиться это значение. Для того что бы найти эту группу
необходимо сравнивать наш хеш 1001 с остальными ключами в словаре, правильно?
В нашем случае к примеру будет так:
a)Сравнение нашего хеша 1001 с первым элементом в словаре, который содержит значение "Маша". В этом случае ключ "Маша" возвращает хеш 1000. Хеши не равны. 1001!=1000.
б) Словарь переходит к следующему элементу. Вычисляет хеш элемента "Саша". Он будет равен 1001. Затем он сравнивает искомый хеш с текущим элементом. 1001==1001. Ага, хеш коды совпали, значит нашли нужный список. Далее с помощью метода Equals он сравнивает ключи. Но они не равны. Искомый у нас "Коля" а текущий "Саша". В итоге он начинает двигаться по линейному списку, переходя к следующему элементу, и находит ключ "Коля".

Правильно?

Добавлено через 19 минут
Цитата Сообщение от kolorotur Посмотреть сообщение
Чтобы не копировать весь массив при каждом добавлении, динамические коллекции, которые в качестве детали реализации используют обычный массив, выделяют память с запасом. Count показывает 5 элементов, а массив в кишках коллекции выделен на 8 элементов — это и есть Capacity.
Прикольно, я не знал=)
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
29.11.2016, 02:43
Цитата Сообщение от Olejan_one Посмотреть сообщение
Для того что бы найти эту группу
необходимо сравнивать наш хеш 1001 с остальными ключами в словаре, правильно?
Нет конечно, иначе словарь ничем не будет отличаться от обычного массива.
На основании сгенерированного хэша словарь высчитывает место нужной корзины за О(1), безо всяких итераций.
Ну например у вас массив из n корзин. Примитивнейший способ нахождения нужной корзины — это взять сгенерированный хэш и найти остаток от деления его на количество корзин (n) — вы сразу же получите местоположение нужной корзины, без итераций.
Разумеется, такой способ может генерировать много коллизий (и генерирует, если GetHashCode плохо реализован), потому на деле там может быть довольно мохнатый матан, но суть в том, что местоположение корзины высчитывается по формуле, без обхода по всем корзинам.
1
1 / 1 / 2
Регистрация: 25.08.2012
Сообщений: 108
29.11.2016, 17:12  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Нет конечно, иначе словарь ничем не будет отличаться от обычного массива.
На основании сгенерированного хэша словарь высчитывает место нужной корзины за О(1), безо всяких итераций.
Ну например у вас массив из n корзин. Примитивнейший способ нахождения нужной корзины — это взять сгенерированный хэш и найти остаток от деления его на количество корзин (n) — вы сразу же получите местоположение нужной корзины, без итераций.
Разумеется, такой способ может генерировать много коллизий (и генерирует, если GetHashCode плохо реализован), потому на деле там может быть довольно мохнатый матан, но суть в том, что местоположение корзины высчитывается по формуле, без обхода по всем корзинам.
Ок спасибо огромное, теперь мне уже более понятнее почему они быстрее. Буду пробовать их использовать!=)
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
30.11.2016, 14:58
kolorotur, поясните пожалуйста следующий момент.
Продолжая пример уважаемого Olejan_one:
В данном словаре:
Цитата Сообщение от Olejan_one Посмотреть сообщение
1000-Маша
1001-Саша->1001-Коля
1002-Вася
1003-Петя
на поиски Коли словарю потребуется две итерации, да?
1) Сначала перейти к линейному массиву совпавших хэшей за одну итерацию.
2) Затем, убедившись, что в нулевом элементе массива неверное значение, начать перебирать массив дальше и во второй итерации, вызвав Equals(Коля) для уже первого элемента массива, обнаружить совпадение.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
30.11.2016, 15:31
Цитата Сообщение от SatanaXIII Посмотреть сообщение
на поиски Коли словарю потребуется две итерации, да?
Итерации там в дело вступают только при нахождении нужной корзины, сама корзина определяется без итеративного процесса.
В конкретном примере для нахождения Коли потребуется три действия:
1. Высчитывание хэша для Коли = 1001
2. Проверка Саша.Equals(Коля) -> false
3. Проверка Коля.Equals(Коля) -> true

Получается, что если хранить в словаре объекты с одинаковыми хэшами, то сложность поиска будет как в обычном массиве: O(n).
1
 Аватар для Serg34
100 / 100 / 33
Регистрация: 20.09.2014
Сообщений: 457
Записей в блоге: 3
09.12.2016, 07:37
Еще иногда проще использовать табличный метод
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
09.12.2016, 07:37
Помогаю со студенческими работами здесь

Программирование без использования встроенных функций matlaba
Доброго времени суток. Помогите пожалуйста с написанием 2 простых программ. 1) Необходимо построить любую полосовую...

Назовите особенности использования вложенных условных операторов
Добрый день! Пожалуйста, помогите правильно ответить на вопросы: 1) Назовите особенности использования вложенных условных операторов. ...

Программирование условных переходов.
Вот задача:

Как обойтись без условных переходов?
И снова здравствуйте. Еще интересует чем можно заменить условные переходы (if..else). Опять же, if..else в дебагере отображаются как джампы...

Как можно сделать без условных операторов?
Проверить утверждения для введенной переменной Х. Программа должна вывести утверждения: 1 Переменная Х целое число 2 Переменная Х...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru