Как определить элемент множества [РЕШЕНО]

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Как определить элемент множества [РЕШЕНО]

Сообщение vada » 05.09.2011 11:52:17

Добрый день форумчане!

Работаю с множествами и наткнулся на проблему. Я не могу определить значение элемента множества. Самое простое, есть множество из N элементов и есть подмножество из K элементов (N>K). Мне требуется в подмножестве определить значение какого любого элемента. Как это сделать не понятно. В цикле перебрать элементы множества и инкрементируя счетчик не очень подходит. Так как очень критично к времени исполнения. И это все в нескольких вложенных циклах. Хорошо бы как в массиве обратиться по индексу, но с множествами такое не проходит.
Кто чего посоветуе?
ЗЫ. Длинну множества тоже хочется определить.
Последний раз редактировалось vada 06.09.2011 11:41:10, всего редактировалось 1 раз.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Как определить элемент множества

Сообщение Mr.Smart » 05.09.2011 12:54:58

Обращение по индексу говорите? да нет ничего проще (зная внутреннее устройства множеств).
Код: Выделить всё
type
  TSet = set of 0..31;

function IsSet(const aSet: TSet; const aIndex: Integer): Boolean;
begin
  Result:=Boolean(dword(aSet) and (1 shl aIndex));
end;
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Как определить элемент множества

Сообщение SAK » 05.09.2011 13:03:08

Что значит "определить значение какого любого элемента"? Это же не массив. Можно определить есть конкретный элемент в множестве или нет.

Mr.Smart писал(а):Обращение по индексу говорите? да нет ничего проще (зная внутреннее устройства множеств).
Код: Выделить всё
...
  Result:=Boolean(dword(aSet) and (1 shl aIndex));
...

А зачем знать внутреннее устройство? Есть же стандартная операция: Result := аIndex in аSet
Но насколько я понял автор топика желает обращаться только к существующим в множестве элементам.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: Как определить элемент множества

Сообщение Mr.Smart » 05.09.2011 13:05:41

SAK точно! Навелосипедничал немного :oops: Понедельник, такой понедельник...
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Как определить элемент множества

Сообщение vada » 05.09.2011 14:16:49

Не. Это не очень. Множество у меня генерится программно и я заранее не знаю его состав. Получить значение true при Index=3 мне не о чем. :( Я не знаю длинну подмножества и не знаю элементы в него входящие. А перебирать в цикле как-то не хочется.
Код: Выделить всё
type
TSetNagr = (ns01, ns02, ns03, ns04, ns05, ns06, ns07, ns08, ns09, ns10,
            ns11, ns12, ns13, ns14, ns15, ns16, ns17, ns18, ns19, ns20);
var
OtherOnly: TSetNagr;


В результате неких манипуляций получаем множество OtherOnly содержащее некоторое количество элементов. Вот мне и хотелось бы определить:
1) Количество элементов в множестве OtherOnly;
2) Значение I-го элемента множества OtherOnly.

Добавлено спустя 2 минуты 29 секунд:
Что значит "определить значение какого любого элемента"? Это же не массив. Можно определить есть конкретный элемент в множестве или нет.

В том и дело что это не массив. Но мне нужно получить значение именно как в массиве. :( И желательно обойтись без циклов.

Например, если третий элемент множества есть ns15 то мне кое-что надо сделать с другим множеством, а если он ns18 то его убрать из множества... Ну где-то так.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Как определить элемент множества

Сообщение Brainenjii » 05.09.2011 15:14:52

Не совсем понял, что именно имеется в виду, но может это поможет:
Код: Выделить всё
TSetNagr = (ns01 = 1, ns02 = 2, ns03 = 3, ns04 = 4, ns05 = 5, ns06 = 24, ns07 = 25, ns08 = 26, ns09 = 33, ns10 = 34,
            ns11 = 38, ns12 = 41, ns13 = 22, ns14 = 90, ns15 = 66, ns16 = 31, ns17 = 29, ns18 = 54, ns19 = 61, ns20 = 66);
...
  WriteLn(Integer(ns13));
...
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Как определить элемент множества

Сообщение vada » 05.09.2011 15:35:30

Не. Не так.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Как определить элемент множества

Сообщение Odyssey » 05.09.2011 15:47:56

vada писал(а):Например, если третий элемент множества есть ns15 то мне кое-что надо сделать с другим множеством, а если он ns18 то его убрать из множества... Ну где-то так.

Множества в паскале не упорядочены, в них не бывает "третьего элемента".
Если важен порядок элементов (например, если ns15 стоит третьим элементом -- нужно сделать что-то с другим множеством, а если четвёртым -- то не нужно ничего делать), то помогут обычные списки (TList или его наследники).
Если порядок элементов не важен, но нужна возможность пробежаться по элементам подмножества, то я бы использовал сортированный список с двоичным поиском по нему. Из коробки двоичный поиск есть только у TStringList, но можно написать собственный список с такой возможностью для другого типа.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Как определить элемент множества

Сообщение vada » 05.09.2011 17:13:18

Odyssey писал(а):Множества в паскале не упорядочены, в них не бывает "третьего элемента".

Жаль. :( Надо что-то другое придумывать.
Хотя, когда я просматриваю сформированное множество, то вижу что оно в том порядке в каком я его создавал. Вот это и натолкнуло на мысль...
А списки не годятся. Это ОЧЕНЬ медленно.
Задача у меня перебрать все варианты из множества длинной максимум 7. Это 7! = 5040 штук комбинаций. Такого порядка множеств у меня 3. Эти три множества надо между собой перемешать. Еще туча вариантов. Какие-то элементы выбрасывать из-за несовместимости. В общем, там дофига переборов получается. :( Уже мозг закипает оптимизировать эту шнягу.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Как определить элемент множества

Сообщение SAK » 05.09.2011 18:02:56

vada писал(а):перебрать все варианты из множества длинной максимум 7

Не знаю всей сути задачи, но на мой взгляд напрашивается просто массив с дополнительной переменной указывающей его размер. Некоторая аналогия типу string. Или ещё добавить функции для упрощения работы с этим массивом и всё объединить в один тип как object или даже класс. Получится аналогия множествам, но с возможностью свободного раширения функциональности.

PS. Количество элементов в множестве называется мощностью множества.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: Как определить элемент множества

Сообщение vada » 06.09.2011 11:40:43

Всем спасибо!
Переработал алгоритм. Скрестил множества со TStringList. Все получилось элегантно понятно и работает быстро.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Как определить элемент множества [РЕШЕНО]

Сообщение CapBuran » 17.03.2012 17:43:28

http://www.pascal.helpov.net/index/pasc ... rogramming

Для работы с перечисляемыми типами существуют следующие функции, которые хранятся в библиотеке системных функций, и программист имеет к ним доступ:

ord(N) – возвращает номер элемента N в множестве;
succ(N) – возвращает следующее значение для N;
pred(N) – возвращает предыдущее значение для N.
CapBuran
незнакомец
 
Сообщения: 1
Зарегистрирован: 17.03.2012 17:36:49


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 6

Рейтинг@Mail.ru