Мелкие задачки для крупных мозгов 12

Тема в разделе "WASM.ZEN", создана пользователем The Svin, 18 мар 2005.

  1. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    В задаче больше математики (но притом полезной с точки зрения ежедневного практического программирования) но и машинной оптимизации в ней есть место.

    Допустим у нас есть массив длин единичных и нулевых строк полученный из задачи 11.

    Нам нужно создать массив представляющий множество которому принадлежат значения из ряда длин

    (на случай если кому то неизвестна разница - в множестве нет повторяющихся элементов т.е. для ряда 1,22,1,13,13

    множество будет {1,22,13})

    До того как мы будем множество это создавать нам нужно выделить память, а она драгоценна, её нужно выделить не меньше чем может понадобится, но и не явно больше (динамическое выделение по принципу - добавим если не хватит - откидывается как неприемлимое по скорости)



    Т.е. нам нужно определить размер памяти больше которой нам явно не понадобится (пусть на размер одного элемента множества выделяется двойное слово).

    Определить это нам нужно исходя из следующих данных (которые у нас есть)

    1. Размер бинарного массива (который дан нам показателем степени двойки например x=27 будет означать что массив в котором считались длины был равен 2^27 или 128и мегабит)

    2. Размер массива с длинами нулевых и единичных строк полученных и массива 1.

    Понятно что мощность множества не может быть больше (2.)

    но оно может быть явно меньше что можно вычислить из (1.)



    Хинт нулевых длин быть не может, любая длина - натуральное число, наибольшее количество значений будет при распределении 1+2+3+... :) а размер массива из которого считали длины - степерь двойки ;)
     
  2. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    вычисление размера массива:
    Код (Text):
    1. in: ecx=x (x<32)
    2. out: eax-максимальное число элементов
    3. calcsize:
    4.     xor eax,eax
    5.     lea edx,[eax+1]
    6.     shl edx,cl
    7.     .l0:
    8.     inc eax
    9.     sub edx,eax
    10.     jnc .l0
    11.     dec eax
    12.     ret


    само множество может потом построю.
     
  3. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Алгоритм компактный, но он резко проигрывает в скорости так же компактному но сделаному после анализа с точки зрения математики.

    В задачке был хинт. Видно что рассмотреть нужно с точки зрения арифметической прогрессии с единицы с шагом 1.

    Т.е. 1+2+3+...+n

    Нам нужно будет найти такое максимально возможное n, которое <= 2<sup>x</sup>

    Далее вспомним что пусть а >=1+2+3+..+n значит

    а >= (n(n+1)):2



    вместо а подставим 2<sup>x</sup> и попробуем сделать преобразования...

    ...ну дальше я удовольствие портить нехочу :)



    Да, давайте уточним действительно что x <= 31 и данная задачка не на построение множества а на нахождение максимальной его мощности для выделения памяти а на элемент требуется 4 байта - нужно выдать уже число в байтах а это можно сделать (учёт размера) немного по разному что тоже скажется на эффективности и по скорости и по размеру.



    Опять прошу - не подходите к задачам с точки зрения тупого сканирования, когда уделяется больше времени лишь на подбор оптимальных инструкций, всё же дискретная математика служит для того чтоб прогрызать дырки в пространстве тупых переборов.
     
  4. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    The Svin

    Зато резко выигрывает в скорости выборка ответа одной командой из таблицы на 32 слова.

    Ну а формула по которой заполняется таблица у меня получилась такая: n=(sqrt(1+2<sup>x+3</sup>)-1)/2 (округляем вверх)
     
  5. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Хех :) Гиганты валятся на мелочах ;)

    А если у тебя количество строк меньше (2. в исходной задаче). Кстати существует компроммисный вариант пара-тройка дополнительных тактов к скорости выборки по индексу и таблички создавать не нужно.
     
  6. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    The Svin



    Нормально работает при x=0..60
    Код (Text):
    1. csz:;(x +4, len +8)->eax
    2.     mov ecx,[esp+4] ;x
    3.     mov eax,$80000000
    4.     mov ebx,eax
    5.     mov edx,eax
    6.     add ecx,3
    7.     shr ecx,1
    8.     jnc .l0
    9.     mov edx,$5A827999
    10.     lea eax,[edx*2+1]
    11.     .l0:   
    12.     shr ebx,cl
    13.     sub eax,ebx
    14.     shr edx,cl
    15.     shr edx,cl
    16.     add eax,edx
    17.     not ecx
    18.     shr eax,cl
    19.     shr eax,1
    20. ;я правильно понял замечание про количество строк?
    21.     cmp eax,[esp+8] ;len(в словах)
    22.     jb .l1
    23.     mov eax,[esp+8]
    24.     .l1:
    25.     ret