Помощь - Поиск - Пользователи - Календарь
Полная версия: Файлы
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Гость
Читал раздел в FAQ и поиск результатов тоже не дал. Помогите с решением задачи!

Дан файл f компонентами которого являются целые числа.Число компонент делится на 4. Никакая из компонент не равна нулю. Файл f содержит равное кол-во отрицательных и положительных компонент.Переписать компоненты этого файла в файл k так, чтобы в файле k числа шли в след. порядке: 2 отрицательных,2 положительных,2 отриц.,2 положит. и т.д.

Подскажите как это реализовать,пожалуйста. Заренее благодарен.
мисс_граффити
Можно пойти таким путем: переносим все отрицательные числа в новый файл, между ними вставляя, например, ноль. То есть получаем последовательность типа
-1 -2 0 0 -4 -5 0 0 -9 -11 0 0
за второй проход заменяем все нули положительными числами из старого файла.
алгоритм упрощается до предела, возвратов назад в файле немного: фактически, все делается за 2 прохода в каждом из файлов.
volvo
Можно сделать за один проход... Вот тут было нечто очень похожее, только там надо было чередовать положительные/отрицательные числа:
Сурсы -> Типизированные файлы
мисс_граффити
там постоянно приходится возвращаться:
seek(f, pos);
...
seek(f, neg);


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

хотя, конечно, новый файл меньше мучаем.
Гость
Хочу задать вопрос...вы посчитаете его думаю глупым,но и всё же. А данный файл f мы используем только для чтения и копирования в другой файл компонен?
volvo
В принципе, это то, что требовалось по условию:
Цитата(Условие)
... Переписать компоненты этого файла в файл k ...
Гость
А что должно быть в самом файле f?
Вот как у меня получается:
var f:file of integer;
fileName:string;
i,n,next:integer;
p:array [1..100] of integer;
begin
Assign(f,'FileName.tip');
rewrite(f);
writeln('Vvedite kol-vo komponent(n/4)');
readln(n);
writeln('Vvedite komponenti(p<>0)');
for i:=1 to n do
begin
readln(p[i]);
end;
close(f);
readln;
end.

Я правильно понимаю,что данные нужно ввести все с клавиатуры? А то, что кол-во положительных и отрицательных компонент в файле нужно просто записать как комментарий например?Или оно должно уравниваться в самом тексте написания файла? Не совсем даже (как оказалось sad.gif ) понимаю как создать днный файл...
мисс_граффити
ты их заносишь в массив, а надо - в файл.
так файл останется пустым.
Гость
нужно просто без массива? так?
var f:file of integer;
fileName:string;
i,n,p,next:integer;
begin
Assign(f,'FileName.tip');
rewrite(f);
writeln('Vvedite kol-vo komponent(n/4)');
readln(n);
writeln('Vvedite komponenti(p<>0)');
for i:=1 to n do
begin
readln(p);
write(f,p);
end;
close(f);
readln;
end.


Гость
Помогите плиз!!!
в самом файле (данном якобы) данные вводиться должны с клавиатуры?Или они должны быть заданы константой, чтобы можно бфло работать с этим файлом...??
мисс_граффити
можешь написать отдельную программку, ею создавать и заполнять файл.
тогда для этой программы файл действительно будет дан.
Гость
Осталось для меня проблемой чередование по 2 отрицательных и положительных компонента.sad.gif Не получается сделать так. Там нужен массив? Если да, то тогда же тип не позволяет создать массив. Просмотрел также и ссылку с похожей задачей...но не смог реализовать именно своё условие...может помогите мне с началом реализовки этого...хочется сделать самому,а никак:(
мисс_граффити
blink.gif зачем массив?
ты пробовал(а) реализовать предложенный мной вариант? показывай попытки...
Гость
Я его даже не сохранил...sad.gif так как постоянно показывало,что тип не соответствует... если не нужен массив... сейчас попробую без массива...
Гость
что-то совсем не получается ничего.Еще и ошибка теперь:(А завтра уже нужно сдавать:(
посмотрите плиз...
Assign(f,'f.dan');
rewrite(f);
Assign(g,'g.dan');
rewrite(g);
writeln('Vvedite kol-vo komponent(n/4)');
readln(n);
writeln('Vvedite komponenti(p<>0):');
for i:=1 to n do
begin
readln(p);
write(f,p);
end;
close(f);
reset(f);
for i:=1 to n do
begin
read(f,p);
write(p,' '); close(f);
reset(f);
for i:=1 to n do
begin
read(f,p);
if p<0 then write(g,p); end;
end;
while not eof(f) do
begin
read(f,p);
if p>0 then write(g,p);
end;
close(g);
reset(g);
for i:=1 to n do
begin
read(g,p);
write(p,' ');
end;
close(f);
close(g);
readln;
end.

мисс_граффити
сделай нормально форматирование - увидишь ошибку.
вложенный цикл по той же переменной...
Гость
одну ошибку я нашел и исправил...
по-прежнему не могу сделать чередование:( Помогите пожалуйста! Сдавать завтра! Не могу понять и всёsad.gif
КМА
А идея остортировать файл не пойдет??? При этом сортировка будет иметь следующий вид.
Первые n/2 элементы будут отрицательными числами, а вторые -- положительными.

Тогда вставлять сразу два из первой половины, и два из второй.

Вся суть состоит только в грамотной сортировке (т. е. на необязательно по возрастанию или убыванию, нам достаточно все отрицательные перенести в правую часть массива). Т. е. мы проходим по первой части и ищем положительные элементы, если мы их нашли, то переходим во вторую часть и ищем отрицательный, затем меняем их местами.
Гость
Сейчас что-то еще попробую.
Может получится отсортировать или еще как-то...sad.gif
Гость
Ничего у меня не получилось с этой программой (видимо него-то не знаю)... Если сможете, то напишите здесь, может до меня всё-таки дойдет. Спасибо.
КМА
должно быть что-то типа этого:

n:=fileSize (f); {количество элементов в файле}
j:=(n div 2) -1;
for i:=1 to n div 2 do
begin
seek (f, i-1);
read (f, buf);
if not (buf<0) {если элемент в первой половине массива не отрицательный}
then
begin
{ищем отрицательный элемент во второй половине}
buf2:=0;
{соответственно на выходе будет buf2 с положительным элементом, и его номер j}
while not (buf2<0) do
begin
seek (f, j);
read (f, buf2);
inc (j);
end;
{j будет хранить текущее положение}
{надо бы обменять значения}
seek (f, i-1);
write (f, buf2);
seek (f, j);
write (f, buf)
end
end;



Знаю, что делаю плохо, т. к. код не проверил. Но тут просто наметка алгоритма. Далее думаю все будет просто, когда ты отсортируешь файл, добавляешь два с переди и два с зади.

Тут n-1 т. к. отсчет файла ведется с нуля.
мисс_граффити
КМА, а теперь представь затраты по времени на сортировку. И ради чего это?
Еще и заданный файл перековеркали... А вдруг он для других целей понадобится.
В общем, если не затруднит, поясни преимущества своего метода.
КМА
По поводу перековеркать, в условие задачи этого не запрещает =)
Реально по поводу памяти согласен, будет менее рационально, и вообще во многом уступает твоему алгоритму, честно, просто хотелось показать еще один вариант.

Мой метод имеет место быть, если скажем половина элементов (а иногда и больше) в правой части отрицательна (хотя может быть с точностью наоборот), тогда будет работать чуть побыстрее твоего, хотя это все еще от кода зависит.
мисс_граффити
Цитата
По поводу перековеркать, в условие задачи этого не запрещает =)

Да я и не говорила, что что-то неправильно... Однако посчитать это достоинством алгоритма не могу.
КМА
Цитата
Однако посчитать это достоинством алгоритма не могу.


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

Но ничего, ведь главное поиск новых решений, было бы с чем сравнивать, иначе никогда не найти оптимальный вариант.
Гость
мисс_граффити, не могла бы ты показать как твой алгоритм должен выглядеть именно на Паскале. Никак я не сделал. Очень прошу!
Гость
Прошу прощения, уже всё сделал. предыдущее сообщение оставлял здесь в отчании,но уже всё сделал. Спасибо всем!
КМА
Можно модернизировать и тому подобное, вообще наколдовал на скорую руку. Необходимые комменты я сделал.


CONST n=8;
VAR inFile, outFile: file of integer;
i, j, k: byte;
buf: integer;
BEGIN
assign (inFile, 'C:\inFile.kma');
{-------------------
Программу желательно сделать отдельно
--------------------}
{это ввод в файл, здесь n просто для удобства, в идеале можно задать любое
n, или запросить у пользователя}
reWrite (inFile);
for i:=1 to n do
begin
write ('Count ->');
readLn (buf);
write (inFile, buf)
end;
close (inFile);
{----------------------}
{Далее идет сама программа, решающая твою задачу по алгоритму miss graffiti}

{т. к. я знаю количество элементов файла, то я сразу пишу n, реально его
можно получить с помощью:
n:=FileSize (inFile) }
assign (outFile, 'C:\outFile.kma');
reWrite (outFile);
reSet (inFile);
j:=0;
for i:=1 to n do {можно и заменить на while not EoF(inFile) do }
begin
read (inFile, buf);
if buf<0
then
begin
inc (j);
write (outFile, buf);
if j=2
then
begin
j:=0;
buf:=0;
write (outFile, buf);
write (outFile, buf)
end
end;
end;
seek (inFile, 0);
j:=2;{ устанвливаем запись 2, т. к. нумерация начинается с 0}
k:=0;
while not EoF (inFile) do
begin
read (inFile, buf);
if buf>=0
then
begin
seek (outFile, j);
write (outFile, buf);
inc (j);
inc (k);
if k=2
then
begin
k:=0;
j:=j+2;
end;
end;
end;
close (inFile);
close (outFile);

{ вывод второго файла}
reSet (outFile);
while not eof (outFile) do
begin
read (outFile, buf);
write (buf, ' ')
end;
readLn;
END.

Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.