IPB
ЛогинПароль:

> 

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

> Оптимальный алгоритм спиральной матрицы
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Кирилл Мамонов
Компонентный Паскаль: Сторонник
Free Pascal: Сторонник
Turbo Pascal: Установлен

Репутация: -  0  +


Здравствуйте! Есть задача - написать оптимизированную по размеру исполняемого файла без ассемблерных вставок(можно использовать прерывания) программу для заполнения матрицы по спирали для случаев от 1 до 9. Задачу решил и написал самый оптимизированный алгоритм, который я смог из себя выдавить. Скажите, что ещё здесь можно оптимизировать или уже стоит приступать к замене ввода на безэховый и вывода через прерывания? Может от каких переменных избавиться? Или циклы оптимизировать можно?
 
program spiral;
var
m: array [1..9, 1..9] of word; //Сама матрица
n: word; //Размерность матрицы
i: word; //Индексы матрицы
j: word;
c: word; //Вводимое число
l: word; //Длина стороны
s: integer; //Флаг меняющийся между значениями -1 и 1
t: word; //Координата поворота
p: ^word; //Указатель на координаты
begin
readln(n);
l := n;
t := n;
s := 1;
i := 1;
p := @j;
repeat
p^ := p^ + s;
c := c + 1;
//Если достигнута точка поворота
if p^ = t then begin
//Меняем изменяемую координату
if p = @j
then begin
p := @i;
l := l - 1;
end else begin
p := @j;
s := -s;
end;
//Узнаём координату следующего поворота
t := p^ + s*(l);
end;
m[i,j] := c;
until l = 0;
//Обычный вывод
for i:=1 to n do begin
for j:=1 to n do write(m[i,j]:3);
writeln;
end;
end.

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
сообщение
Сообщение #2





Группа: Пользователи
Сообщений: 8
Пол: Мужской

Репутация: -  0  +


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

Цитата
написать оптимизированную по размеру исполняемого файла

-и сколько получилось?

Матрица по спирали - попробуйте, сравните.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Кирилл Мамонов
Компонентный Паскаль: Сторонник
Free Pascal: Сторонник
Turbo Pascal: Установлен

Репутация: -  0  +


Цитата(Халявов @ 21.12.2017 22:32) *

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

Цитата
написать оптимизированную по размеру исполняемого файла

-и сколько получилось?

Матрица по спирали - попробуйте, сравните.


Моя после компиляции без всяких особых натроек компилятора весит 3104 байта
Вами, приведённая 3776 байт

Задано в КубГУ, ну как задано... За самую маленькую в группе самоэкз получить можно)
Рекорд за всё время говорят где-то к 1200 байт приблизился.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4





Группа: Пользователи
Сообщений: 8
Пол: Мужской

Репутация: -  0  +


Цитата(Akusov @ 24.12.2017 2:13) *
Моя после компиляции без всяких особых натроек компилятора весит 3104 байта
А чем компилировали? Поделитесь секретом smile.gif

Сообщение отредактировано: Халявов -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Кирилл Мамонов
Компонентный Паскаль: Сторонник
Free Pascal: Сторонник
Turbo Pascal: Установлен

Репутация: -  0  +


Цитата(Халявов @ 24.12.2017 1:42) *

Цитата(Akusov @ 24.12.2017 2:13) *
Моя после компиляции без всяких особых натроек компилятора весит 3104 байта
А чем компилировали? Поделитесь секретом smile.gif


BPC Старый добрый BPC. Это собственно и есть компилятор для соревнований. Всё в досбоксе собирается.


Добавлено через 3 мин.
Счёт идёт на байты. Вообще задание полностью так звучит - Нужно написать две программы спиральной матрицы для размерность от 2 до 9. Одну на ассемблере, другую на паскале и в суме они должны быть меньше 3000 байт, и тот чья прога меньше остальных, тот и получает самоэкз. В программе на паскале использовать asm end. Запрещено.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6





Группа: Пользователи
Сообщений: 8
Пол: Мужской

Репутация: -  0  +


Понятно, Ассемблер всё объясняет. А то задача выглядит как злобный троллинг препода.

Я бы начал думать как сэкономить на WriteLn. Теоретически, у вас два вызова с разным набором параметров.
На Си можно было бы сделать подобие
printf("..формат..", Элемент_Массива, i==n?"\n":" ");
хотя само вычисление может оказаться большим.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Кирилл Мамонов
Компонентный Паскаль: Сторонник
Free Pascal: Сторонник
Turbo Pascal: Установлен

Репутация: -  0  +


Цитата(Халявов @ 24.12.2017 2:15) *

Понятно, Ассемблер всё объясняет. А то задача выглядит как злобный троллинг препода.

Я бы начал думать как сэкономить на WriteLn. Теоретически, у вас два вызова с разным набором параметров.
На Си можно было бы сделать подобие
printf("..формат..", Элемент_Массива, i==n?"\n":" ");
хотя само вычисление может оказаться большим.

В том то и дело. Он говорил, что можно использовать в паскале прерывания(безэховый ввод в частности), но нельзя ассемблерные вставки. Да и даже с учётом, что вторая прога на ассемблере, рекорд на паскале всё равно остаётся 1200 байт. Побить я его конечно не стремлюсь(да и вряд ли возможно), но как вообще в принципе можно приблизиться хотя бы 1500-1800 байт на паскале? Пытался использовать модуль dos с его Intr и MsDos, но программа становится больше, что меня не устраивает. Пока, косо смотрю в сторону interrupt-процедур, но толковой документации я не нашёл и я вообще не знаю, могут ли они дать мне уменьшение в размерах?(там вроде как регистры можно использовать, но использует ли их реально компилятор на выходе я не знаю).
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 194
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: bu_gen@octagram.name
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


Цитата(Akusov @ 24.12.2017 6:32) *
Пытался использовать модуль dos с его Intr и MsDos, но программа становится больше, что меня не устраивает. Пока, косо смотрю в сторону interrupt-процедур, но толковой документации я не нашёл и я вообще не знаю, могут ли они дать мне уменьшение в размерах?(там вроде как регистры можно использовать, но использует ли их реально компилятор на выходе я не знаю).


Turbo Pascal позволяет написать свою interrupt-процедуру, но не определить указатель на неё. Когда я пытаюсь написать

type THandler = procedure(AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt;


… Turbo Pascal ругается на отсутствие = после interrupt. Похоже, у указателей на процедуры вообще не может быть директив.

Ситуация всё же не безнадёжная. Мне удалось вызвать прерывание 16#21# (AH => 16#09#). Вызов прерываний как программных, так и аппаратных, похож на далёкий вызов, но в стек помещается также и регистр флагов. Инструкция iret, которой заканчиваются обработчики прерываний, в отличие от retf, также и возвращает состояние этого регистра. Если в Турбо Паскале указатели на процедуры могут быть только обычными, мне пришла в голову идея объявить тип указателя на прерывание как принимающий один аргумент. И чтоб передавать потом в этот аргумент типичное состояние флагов, которое я вывел на экран ассемблерной процедурой, не попадающей в конечный результат.

Далее, вот конкретно подвызов AH => 16#09# принимает адрес строки в DS:DX. Соответственно, надо как-то подстроить, чтоб там оказались нужные значения. Почти надёжный способ с AX и DX — это устроить возврат LongInt. LongInt возвращается в DX:AX, старшее слово — в DX, младшее — в AX. На DS я повлиять не могу, он спроецирован на общий для всей программы сегмент данных. Так что нужно, чтоб буфер был там. То есть, это обязательно глобальная переменная.

Итак, мне нужна функция, которая сконструирует DX:AX, вернув подходящее значение. Это значение будет сразу же «выброшено», но функция-то об этом не знает. Возвращать лучше бы DWord, но в Turbo Pascal такого типа нет, а есть только знаковый LongInt. Это плохо. Вдруг старший бит DX будет выставлен? Значит, я сначала получаю значение DX как есть (тип Word), потом привожу к Integer, что в Турбо Паскале часто работает как Unchecked_Conversion в языке Ада или reinterpret_cast в C++. Потом надо это значение сдвинуть на 16 бит в верхнее слово, но сначала ещё раз привести тип, на этот раз — к LongInt. А после этого при помощи «or $0900» инициализировать будущий AH.

Я использовал GetIntVec из модуля Dos. Вы можете переделать на прямой доступ к таблице прерываний, но осторожно. Между функцией, которая конструирует DX:AX, и вызовом прерывания по возможности не должно быть никаких вычислений, которые могли бы уничтожить AX. А доступ по прямому адресу чреват чем-то таким. Так что надо сохранить этот адрес заранее поближе. С глобальными переменными, как я вижу, работает хорошо.


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме
Akusov   Оптимальный алгоритм спиральной матрицы   20.12.2017 5:31
OCTAGRAM   Какая-то довольно специфическая оптимизация. На фо…   20.12.2017 14:11
Халявов   Интересно, в каком вузе дают подобные программы? Н…   22.12.2017 2:32
Akusov   Интересно, в каком вузе дают подобные программы? …   24.12.2017 2:13
Akusov   Как думаете? Вообще реально написать такую програм…   24.12.2017 4:18
Халявов   Моя после компиляции без всяких особых натроек ком…   24.12.2017 5:42
Akusov   Моя после компиляции без всяких особых натроек ко…   24.12.2017 5:56
Халявов   Понятно, Ассемблер всё объясняет. А то задача выгл…   24.12.2017 6:15
Akusov   Понятно, Ассемблер всё объясняет. А то задача выг…   24.12.2017 6:32
OCTAGRAM   Пытался использовать модуль dos с его Intr и MsDos…   27.12.2017 5:33
Akusov   В общем. Немного модифицировал и обнаружил, что те…   24.12.2017 8:40
Akusov   Как ни странно - я смог ужать программу ещё сильн…   24.12.2017 10:41
Akusov   Пораскинув мозгами, смог ужать итоговый екзешник д…   25.12.2017 23:36
Akusov   Я изучив exe-шник - обнаружил длиннющую строку с и…   26.12.2017 3:46
Akusov   Последние вести с полей. Уменьшил прогу до 1936 ба…   26.12.2017 5:14
Федосеев Павел   Можно ещё чуток, если заменить 1. bx := bx + 1; на…   27.12.2017 0:24
Akusov   Можно ещё чуток, если заменить 1. bx := bx + 1; н…   27.12.2017 3:14
Akusov   Решил попробовать компилятор Turbo Pascal 5.5 В ко…   28.12.2017 11:55
Халявов   Turbo Pascal 5.5 В командной строке набираю TPC SP…   28.12.2017 12:05
Akusov   Turbo Pascal 5.5 В командной строке набираю TPC S…   28.12.2017 17:11
OCTAGRAM   Можно ещё попробовать директивами отключить эмуляц…   28.12.2017 18:04
Akusov   Можно ещё попробовать директивами отключить эмуля…   29.12.2017 4:21
Akusov   Уже 1680. Нашёл просто дичайшую неоптимизированнос…   29.12.2017 4:45


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 27.04.2024 22:25
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name