Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет qwerty ([info]qwerty)
@ 2010-01-24 17:11:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Задачка

Есть одномерный массив целых. В начале его расположен массив A длиной a, в конце B длиной b, а посредине не интересующий нас мусор длиной c. Требуется красивым образом переместить B в начало, за ним расположить A, причем сделав при этом не более a+b чтений и записей в массив. Судьба мусора не интересует. Файлы, посторонняя память и рекурсия категорически отсутствуют.


(Читать комментарии) - (Добавить комментарий)


[info]phantom
2010-01-25 19:53 (ссылка)
Здесь тот же контрпример подходит, что и к моему решению.

>Ну и на пару переменных место не "категорически отсутствует".

Есть приём перестановки значений переменных без использования дополнительной переменной.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ppkk
2010-01-25 20:39 (ссылка)
Да, слажал я.

Про "хитрые" перестановки: в итоге (в общем случае) может быть, что должно измениться каждое число (из примера: для 1 2 3 0 4 5 — 4 5 1 2 3 ?). Значит (хотя бы в некоторых ситуациях) каждая запись придаёт окончательное значение числу в ячейке, кроме того, каждая ячейка массивов A и B должна быть прочитана хотя бы по разу, а значит и не более раза.

Так что целочисленные хитрости вряд ли годятся (либо я неправильно понимаю условие, а у нас на самом деле есть возможность совершать арифметические действия со значениями ячеек, якобы "не читая" и "не записывая"). Если происходит: M[x] := M[y] + M[z] или M[x] := M[x] + M[y], то я считаю, что происходит два чтения и одна запись. Обмен значениями M[x] и M[y] — два чтения, две записи и две ячейки памяти.

Указание http://lj.rossia.org/users/qwerty/132388.html?thread=505892#t505892 , что: "Ну и, кроме того, c может быть нулевым,"— заставляют меня упереться в случай a=b=1, c=0 без понимания того, как результат достигается.

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

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2010-01-25 21:11 (ссылка)
>каждая запись придаёт окончательное значение числу в ячейке, кроме того,
>каждая ячейка массивов A и B должна быть прочитана хотя бы по разу, а значит и не
>более раза.


Да, вроде того.

>Обмен значениями M[x] и M[y] — два чтения, две записи и две ячейки памяти.

Две записи и 4 чтения вроде.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ppkk
2010-01-25 21:22 (ссылка)
Две записи и 4 чтения вроде.
Не знаю, как ты это насчитал, но случай a=b=1, c=0 определённо нуждается в пояснениях.

В этом обсуждении деталей явно меньше, чем в вопросе http://bytes.com/topic/algorithms/answers/875234-remapping-elements-array (позабавили комментарии)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2010-01-25 22:57 (ссылка)
Я имел в виду классическую (хм) задачу:

x = x + y;
y = x - y;
x = x - y;

Ой, ошибся там. 6 чтений, 3 записи.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ppkk
2010-01-25 23:30 (ссылка)
Ответ: x=y=0?:)

Как задачу это не встречал, вероятно и потому, что так обожали менять значения в программах-примерах: составителям, в отличие от меня, это нравилось.

При таких раскладах (особенно если вопят об отсутствии памяти) кажется единственной возможной операция по записи числа на "пустое" мето. Я торопился, так что предположил, что c=0 не бывает, рассмотрел c=1, там всё однозначно (и, как я не удосужился проверить, не работает), а дальше однозначно обобщил на c>1. Так как "задачка" оказалась из жанра "угадай условие", буду ждать, когда [info]qwerty@lj самоудовлетворённо напишет, что все идиоты, а он Д'Артаньян: видимо, узнаю и условия, и решение, алгоритм по-любому должен быть интересным.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2010-01-26 11:51 (ссылка)
>Как задачу это не встречал, вероятно и потому, что так обожали менять значения в
>программах-примерах: составителям, в отличие от меня, это нравилось.


В книге Шеня идёт как задача, правда, сразу с решением.

>видимо, узнаю и условия, и решение, алгоритм по-любому должен быть интересным.

Сомневаюсь, т.к. эти задачи скорее для разминки мозга, нежели несущие какую-либо практическую ценность.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ppkk
2010-01-26 17:33 (ссылка)
скорее для разминки мозга, нежели несущие какую-либо практическую ценность
Зависит от работы.
Я устроился программистом (криптография-криптоанализ) — "эти задачи" были актуальны, но тянуло к переписыванию на ассемблере с SSE и прочей жутью. А сейчас просто тупо программирую то, в чём редко надо умничать. Но задачи типа упрощённого движка шаблонов или операций со списками, которые должны быть эффективными, порой встречаются: многие их решают неправильно. Или с базами данных бывает над чем подумать.

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

(Ответить) (Уровень выше)


[info]ppkk
2010-01-25 23:38 (ссылка)
Тут и сложение, и вычитание, и неизвестно, где хранятся значения аргументов во время вычисления.

Так можно предположить, например, что для всевозможных перестановок τ l<=10-и элементов есть операция τ(x1,…,xl), которая переставляет в массиве элементы с заданными индексами согласно τ, причём засчитывается за l чтений и l записей, не требуя дополнительной памяти:)

Кроме того, если это "математические" целые числа, то мы можем за один проход по важным числам неизвестно где (если к циклам не придирались, то в счётчике?) закодировать их все, после чего в один проход раскодировать куда надо.

Жду автора на белом коне, в общем…

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-26 00:10 (ссылка)
http://lj.rossia.org/users/qwerty/132388.html?thread=509988#t509988

(Ответить) (Уровень выше)


[info]phantom
2010-01-26 11:56 (ссылка)
Правильно, промежуточным переменным негде храниться, кроме как в дополнительной ячейке памяти (регистре). Поэтому и ценность исключительно педагогическая.

Кстати, у меня один знакомый был, который программируя на одном чипе, утверждал, что он считает ДПФ по стандартной формуле быстрее, чем БПФ, благодаря операции умножения с накоплением.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-26 13:19 (ссылка)
Про отсутствие небольшого числа регистров нигде не говорилось. Теперь я понимаю, почему пришлось Кнуту придумать свой абстрактный вычислитель.

Белого коня не будет - мне свое решение красивым не кажется. Но я еще надеюсь его придумать.

В части ограничения памяти задача вполне практическая, а сугубые
ограничения на число чтений и записей, конечно, для забавы. Из практически приемлемых самое красивое в худшем случае делает 3a+2b+c чтений и записей с хорошей локальностью.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2010-01-26 13:29 (ссылка)
А вот нехорошо давать задачи, которые не имеют решения. Или надо оговаривать, что проблема открытая. Также стоило сказать, что это практическая задача - это в корне меняет подход.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-26 13:51 (ссылка)
Эээ... Чего это вдруг она не имеет решения? От того, что вы вдруг обнаружили, что где-то нужно хранить локальные переменные?

В указанных ограничениях эта задача практической не является.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2010-01-26 15:06 (ссылка)
Может быть, она и решаемая. Но по способу подачи некоторым показалось, что это задание по типу олимпиадного. Обычно автор знает ответ в этом случае (вот лично я бы не стал тратить время на размышления, зная, что автор решения не знает).

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-26 15:39 (ссылка)
У автора имеется решение, удовлетворяющее всем критериям, кроме субъективного эстетического.

Ниже [info]blue_slonopotam@lj предлагает свое решение. Я пока не проверил, верное ли оно. Оно меня эстетически тоже не особенно вдохновляет вычислением Н.О.Д., но это-то наверняка поправимо.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]blue_slonopotam
2010-01-27 01:42 (ссылка)
Ты тоже не забудь показать, мне интересно.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-27 01:55 (ссылка)
У меня все на сложениях и вычитаниях с другим критерием завершения, но мне не нравится мой буфер на локале с флагом заполнения и разбор нескольких частных случаев перед. От флага могу избавиться хитрой проверкой, но красивее от этого не становится.

Собственно, GCD классически считается вычитаниями:
unsigned gcd(unsigned a, unsigned b) {
  if (a == 0) {
    return b;
  }
  while (b) {
    if (a > b) {
      a -= b;
    } else {
      b -= a;
    }
  }
  return a;
}

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]blue_slonopotam
2010-01-27 02:43 (ссылка)
"У автора имеется решение"

Я не про НОД, а про всю программу. Я почти уверен, что она работает так же, как и моя, но выглядит совершенно иначе.

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

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-27 03:10 (ссылка)
Ну, все-таки, ты пока не предъявил программы, выполняющей не более a+b чтений и записей. Условия завершения пока разные, про мусор сказать еще ничего нельзя.

У меня нет вычисления НОД. Но подозреваю, что попутно производимые действия со сложениями и вычитаниями ему эквивалентны.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]blue_slonopotam
2010-01-27 03:13 (ссылка)
Мы с тобой быдлокодеры. Джаниторз митинг, не иначе.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]qwerty
2010-01-27 03:17 (ссылка)
Почему же сразу быдлокодеры? Просто в голове много заезженных паттернов застряло, они оттуда чуть что лезут. Но до TCHAR я пока не докатился, нет :)

(Ответить) (Уровень выше)


[info]tristes_tigres
2010-01-28 14:17 (ссылка)
выполняющей не более a+b чтений и записей.
См

(Ответить) (Уровень выше)


[info]ppkk
2010-01-27 18:33 (ссылка)
Я рассматривал способы расстановки с начала цепочками их по местам (то есть: обработать позиции 1…(a+b)):
1. Проверить, что это следует делать (ниже).
2. Сохранить значение с первого места, записать туда то (с места X), что полагается, посмотреть, куда надо записать то, что стояло на первом месте, если надо — сохранить и продолжать, если не надо — записать. На начальную позицию повторно не пишем, если до неё дошли.
3. Если не доходили до начальной позиции, то заполняем в обратном направлении, если требуется (писать на место X и т.п.).

Проверка, что это следует делать: идём по цепочкам, только проверяя индексы, не выполняя операций load/store. Если встретился индекс меньше исходного, то делать не надо.

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

Требуемой красоты определённо не наблюдается: случаи разных соотношений a, b и c заметно отличаются. В случае c=0 формулы, например, могут быть проще (там будут циклы). Или в случае a=b, c=ka. В "олимпиадной задече" по [info]phantom-у, видимо, должны были бы стоять и "красивые" соотношения a, b и c…

(Ответить) (Уровень выше)


(Читать комментарии) -