Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2016.05.01;
Скачать: CL | DM;

Вниз

Головоломка выходного дня.   Найти похожие ветки 

 
Sha ©   (2015-08-14 23:58) [0]

Предположим, что разработчики Delphi вместо замечательного типа TDateTime
придумали тип TDayTime, который в int64-переменной хранит неотрицательное время
в битовом представлении в формате дни:часы:минуты:секунды следующим образом:

dddd dddd dddd dddd dddd dddd dddd dddd dddd dddd dddd dddh hhhh mmmm mmss ssss


Требуется без использования операций деления-умножения написать процедуры:

procedure DayTimeAdd(p1, p2, p3: PDayTime); //p3^:=p1^+p2^
function DayTimeSub(p1, p2, p3: PDayTime): boolean; //p3^:=abs(p1^-p2^); result:=(p1>p2)


 
Sha ©   (2015-08-15 00:43) [1]

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


 
NoUser ©   (2015-08-15 21:20) [2]

// 30-строчек кода: 4-сложения, 4-вычитания, 10-сравнений( 3-или, 12-масок ) .


 
Dennis I. Komarov ©   (2015-08-15 21:37) [3]

Не умные программисты такое придумали - это еще и валидность значения каждый раз проверять надо...
DayTimeToStr($3F)?


 
NoUser ©   (2015-08-15 21:58) [4]

>  валидность значения каждый раз проверять надо
так оно везде так, в этом суровом мире ))

TFloatSpecial = ( ...., fsDenormal, fsNDenormal, .... fsInf, fsNInf, fsNaN );
DateTimeToStr( NaN )?


 
Sha ©   (2015-08-15 23:07) [5]

> NoUser ©   (15.08.15 21:20) [2]

есть вариант попроще


 
SergP ©   (2015-08-17 10:29) [6]


> Побеждает решение  с минимальным количеством операторов.
>
> Включая и IFы и их внутренности.


c:=a+b;
это один оператор или два (сложение и присваивание)?

c:=a+b+c+d; - это сколько операторов?


 
SergP ©   (2015-08-17 10:56) [7]


> procedure DayTimeAdd(p1, p2, p3: PDayTime); //p3^:=p1^+p2^


Если без всяких проверок валидности, то приблизительно (не проверял или будет правильно работать), должно быть так:

procedure DayTimeAdd(p1, p2, p3: PDayTime);
begin
 p3:=p1+p2;
 p3:=(((p3+$8104) xor p3 or $21040) shr 4 +$3000) and $4104+p3;
end;

хотя оно слишком мутное, могу и ошибаться...


 
SergP ©   (2015-08-17 11:01) [8]

не. там я явно ошибся...
вроде так правильнее:
procedure DayTimeAdd(p1, p2, p3: PDayTime);
begin
p3:=p1+p2;
p3:=(((p3+$8104) xor p3 or $21040) shr 4 +$6000) and $8104+p3;
end;


 
SergP ©   (2015-08-17 12:10) [9]

не. вроде нифига не правильно


 
SergP ©   (2015-08-17 12:20) [10]

procedure DayTimeAdd(p1, p2, p3: PDayTime);
begin
p3:=p1+p2;
p3:=(((p3+$8104) xor p1 xor p2 or $21040) shr 4 +$6000) and $8104+p3;
end;


 
SergP ©   (2015-08-17 13:08) [11]

Вроде так: (без проверок на валидность исходных данных)
procedure DayTimeAdd(p1, p2, p3: TDayTime);
begin
p3:=p1+p2;
p3:=(((p3+$8104) xor p1 xor p2 or $21040) shr 4 +$6000) and $8104+p3;
end;

function DayTimeSub(p1, p2, p3: TDayTime): boolean;
 result:=p1>p2;
 DayTimeAdd(p1, $80c4-p2, p3);
end;


Если с указателями, то хз, иногда путаюсь с ними:

procedure DayTimeAdd(p1, p2, p3: PDayTime);
begin
p3^:=p1^+p2^;
p3^:=(((p3^+$8104) xor p1^ xor p2^ or $21040) shr 4 +$6000) and $8104+p3^;
end;

function DayTimeSub(p1, p2, p3: PDayTime): boolean;
 result:=p1^>p2^;
 DayTimeAdd(p1, @($80c4-p2^), p3);
end;


 
SergP ©   (2015-08-17 13:12) [12]


> procedure DayTimeAdd(p1, p2, p3: TDayTime);
> begin
>  p3:=p1+p2;
>  p3:=(((p3+$8104) xor p1 xor p2 or $21040) shr 4 +$6000)
> and $8104+p3;
> end;
>  
> function DayTimeSub(p1, p2, p3: TDayTime): boolean;
>   result:=p1>p2;
>   DayTimeAdd(p1, $80c4-p2, p3);
> end;


Опять ошибка, не $80c4, а -$80c4

procedure DayTimeAdd(p1, p2, p3: TDayTime);
begin
p3:=p1+p2;
p3:=(((p3+$8104) xor p1 xor p2 or $21040) shr 4 +$6000) and $8104+p3;
end;

function DayTimeSub(p1, p2, p3: TDayTime): boolean;
 result:=p1>p2;
 DayTimeAdd(p1, -$80c4-p2, p3);
end;


 
SergP ©   (2015-08-17 13:13) [13]

М-да... Ну и нафлудил я тут ))))


 
Sha ©   (2015-08-17 13:45) [14]

Во-первых хочу исправить небольшую неточность в условии:
при вычитании функция должна возвращать result:=(p1>=p2), а не result:=(p1>p2).

> SergP

Немного подправил функции, чтобы они компилировались:
procedure DayTimeAddSergP(p1, p2, p3: pint64);
begin
 p3^:=p1^+p2^;
 p3^:=(((p3^+$8104) xor p1^ xor p2^ or $21040) shr 4 +$6000) and $8104+p3^;
end;

function DayTimeSubSergP(p1, p2, p3: pint64): boolean;
var
 tmp: int64;
begin
 result:=p1^>=p2^;
 tmp:=-$80c4-p2^;
 DayTimeAddSergP(p1, @tmp, p3);
end;


Обе функции тест провалили. Тест не исчерпывающий, но достаточно полный:

procedure TForm1.Button3Click(Sender: TObject);
var
 d1, h1, m1, s1: integer;
 d2, h2, m2, s2: integer;
 d3, h3, m3, s3: integer;
 i1, i2: integer;
 t1, t2, t3: integer;
 v1, v2, v3: integer;
 x1, x2, x3: int64;
begin;
 for i1:=0 to $1FFF do begin;
   d1:=i1 shr 12;                               t1:=d1 shl 17;       v1:=     d1 * (60*60*24);
   h1:=i1 shr 8 and 15; h1:=h1 + h1 and 8;      t1:=t1 or h1 shl 12; v1:=v1 + h1 * (60*60);
   m1:=i1 shr 4 and 15; if m1>7 then m1:=m1+44; t1:=t1 or m1 shl 6;  v1:=v1 + m1 * 60;
   s1:=i1       and 15; if s1>7 then s1:=s1+44; t1:=t1 or s1;        v1:=v1 + s1;

   for i2:=0 to $1FFF do begin;
     d2:=i2 shr 12;                               t2:=d2 shl 17;       v2:=     d2 * (60*60*24);
     h2:=i2 shr 8 and 15; h2:=h2 + h2 and 8;      t2:=t2 or h2 shl 12; v2:=v2 + h2 * (60*60);
     m2:=i2 shr 4 and 15; if m2>7 then m2:=m2+44; t2:=t2 or m2 shl 6;  v2:=v2 + m2 * 60;
     s2:=i2       and 15; if s2>7 then s2:=s2+44; t2:=t2 or s2;        v2:=v2 + s2;

     x1:=t1;
     x2:=t2;
     DayTimeAdd(@x1, @x2, @x3);
     t3:=x3;

     d3:=t3 shr 17;         v3:=     d3 * (60*60*24);
     h3:=t3 shr 12 and $1f; v3:=v3 + h3 * (60*60);
     m3:=t3 shr 6 and $3f;  v3:=v3 + m3 * 60;
     s3:=t3 and $3f;        v3:=v3 + s3;

     if v3<>v1+v2 then begin;
       Memo1.Lines.Add(Format("%d %d %d %d",[d1,h1,m1,s1]));
       Memo1.Lines.Add(Format("%d %d %d %d",[d2,h2,m2,s2]));
       Memo1.Lines.Add(Format("%d %d %d %d",[d3,h3,m3,s3]));
       Memo1.Lines.Add("failed");
       exit;
       end;

     end;
   end;

 Memo1.Lines.Add("done")
 end;

procedure TForm1.Button4Click(Sender: TObject);
var
 d1, h1, m1, s1: integer;
 d2, h2, m2, s2: integer;
 d3, h3, m3, s3: integer;
 i1, i2: integer;
 t1, t2, t3: integer;
 v1, v2, v3: integer;
 x1, x2, x3: int64;
 res: boolean;
begin;
 for i1:=0 to $1FFF do begin;
   d1:=i1 shr 12;                               t1:=d1 shl 17;       v1:=     d1 * (60*60*24);
   h1:=i1 shr 8 and 15; h1:=h1 + h1 and 8;      t1:=t1 or h1 shl 12; v1:=v1 + h1 * (60*60);
   m1:=i1 shr 4 and 15; if m1>7 then m1:=m1+44; t1:=t1 or m1 shl 6;  v1:=v1 + m1 * 60;
   s1:=i1       and 15; if s1>7 then s1:=s1+44; t1:=t1 or s1;        v1:=v1 + s1;

   for i2:=0 to $1FFF do begin;
     d2:=i2 shr 12;                               t2:=d2 shl 17;       v2:=     d2 * (60*60*24);
     h2:=i2 shr 8 and 15; h2:=h2 + h2 and 8;      t2:=t2 or h2 shl 12; v2:=v2 + h2 * (60*60);
     m2:=i2 shr 4 and 15; if m2>7 then m2:=m2+44; t2:=t2 or m2 shl 6;  v2:=v2 + m2 * 60;
     s2:=i2       and 15; if s2>7 then s2:=s2+44; t2:=t2 or s2;        v2:=v2 + s2;

     x1:=t1;
     x2:=t2;
     res:=DayTimeSubSergP(@x1, @x2, @x3);
     t3:=x3;

     d3:=t3 shr 17;         v3:=     d3 * (60*60*24);
     h3:=t3 shr 12 and $1f; v3:=v3 + h3 * (60*60);
     m3:=t3 shr 6 and $3f;  v3:=v3 + m3 * 60;
     s3:=t3 and $3f;        v3:=v3 + s3;

     if (res<>(v1>=v2)) or (v3<>abs(v1-v2)) then begin;
       Memo1.Lines.Add(Format("%d %d %d %d",[d1,h1,m1,s1]));
       Memo1.Lines.Add(Format("%d %d %d %d",[d2,h2,m2,s2]));
       Memo1.Lines.Add(Format("%d %d %d %d",[d3,h3,m3,s3]));
       Memo1.Lines.Add("failed");
       exit;
       end;

     end;
   end;

 Memo1.Lines.Add("done")
 end;


 
SergP ©   (2015-08-17 14:03) [15]

Эх. не получилось написать не используя компилятор.... пришлось запускать Delphi
В первой функции нашел ошибку:
там вместо or нужно and

procedure DayTimeAddSergP(p1, p2, p3: pint64);
begin
 p3^:=p1^+p2^;
 p3^:=((((p3^+$8104) xor p1^ xor p2^) and $21040) shr 4 +$6000) and $8104+p3^;
end;


со второй пока думаю


 
SergP ©   (2015-08-17 14:09) [16]

Вторая функция обязана передавать в p3 корректный результат, если ее значение false?


 
SergP ©   (2015-08-17 14:14) [17]

Насчет [16], дело в том, что немного подправил вторую функцию:

function DayTimeSubSergP(p1, p2, p3: pint64): boolean;
var
 tmp: int64;
begin
 result:=p1^>=p2^;
 tmp:=-$8104-p2^;
 DayTimeAddSergP(p1, @tmp, p3);
end;


Но тест все равно ее фейлит таким образом:

0 0 0 0
0 0 0 1
32767 23 59 59
failed


 
Sha ©   (2015-08-17 14:14) [18]

> SergP ©   (17.08.15 14:09) [16]

Да, но в этом случае результат должен быть как если бы из p2 вычитали p1.


 
Sha ©   (2015-08-17 14:18) [19]

Sha ©   (17.08.15 14:14) [18]
т.е. если false, то надо получить p3=p2-p1


 
SergP ©   (2015-08-17 14:27) [20]

ну в таком случае получается:

procedure DayTimeAddSergP(p1, p2, p3: pint64);
begin
 p3^:=p1^+p2^;
 p3^:=((((p3^+$8104) xor p1^ xor p2^) and $21040) shr 4 +$6000) and $8104+p3^;
end;

function DayTimeSubSergP(p1, p2, p3: pint64): boolean;
var
 tmp: int64;
begin
 result:=p1^>=p2^;
 tmp:=-$8104-p2^;
 DayTimeAddSergP(p1, @tmp, p3);
 if not result then p3^:=-$8104-p3^;
end;


 
SergP ©   (2015-08-17 14:40) [21]

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

procedure DayTimeAddSergP(p1, p2, p3: pint64);
begin
 p3^:=p1^+p2^;
 p3^:=((((p3^+$8104) xor p1^ xor p2^) and $21040) shr 4 +$6000) and $8104+p3^;
end;

function DayTimeSubSergP(p1, p2, p3: pint64): boolean;
begin
 result:=p1^>=p2^;
 p2^:=-$8104-p2^;
 DayTimeAddSergP(p1, p2, p3);
 if not result then p3^:=-$8104-p3^;
end;


 
Sha ©   (2015-08-17 14:44) [22]

> SergP ©   (17.08.15 14:27) [20]

Здорово.
А я не додумался до $6000:
const
 dtCarry = $00021040;
 dtRest  = $00008104;

procedure DayTimeAddSha(p1, p2, p3: PDayTime); //p3^:=p1^+p2^
var
 delta: integer;
begin;
 delta:=(p1.Lo xor p2.Lo xor (p1.Lo + p2.Lo + dtRest)) and dtCarry;
 pInt64(p3)^:=(delta shr 4 or delta shr 2) and dtRest + pInt64(p1)^ + pInt64(p2)^;
 end;

function DayTimeSubSha(p1, p2, p3: PDayTime): boolean; //p3^:=abs(p1^-p2^); result:=(p1>=p2)
var
 delta: integer;
begin;
 if pInt64(p1)^ >= pInt64(p2)^ then begin;
   delta:=(p1.Lo xor p2.Lo xor (p1.Lo - p2.Lo)) and dtCarry;
   pInt64(p3)^:=-((delta shr 4 or delta shr 2) and dtRest) + pInt64(p1)^ - pInt64(p2)^;
   Result:=true;
   end
 else begin; //p1^ < p2^
   delta:=(p2.Lo xor p1.Lo xor (p2.Lo - p1.Lo)) and dtCarry;
   pInt64(p3)^:=-((delta shr 4 or delta shr 2) and dtRest) + pInt64(p2)^ - pInt64(p1)^;
   Result:=false;
   end;
 end;


Получилось длиннее, потому что еще старался не потерять эффективность.


 
Sha ©   (2015-08-17 14:46) [23]

> SergP ©   (17.08.15 14:40) [21]

нет, так не надо, испортишь переданные данные


 
Sha ©   (2015-08-17 14:47) [24]

Sha ©   (17.08.15 14:44) [22]

потерял
type
 PDayTime= ^Int64Rec;


 
Sha ©   (2015-08-17 17:06) [25]

В общем, вот что вышло в итоге:

type
 PDayTime= ^Int64Rec;

const
 dtCarry = $00021040;
 dtRest  = $00008104;
 dtSergP = $00006000; //преобразует двухчасовую дельту к восьмичасовой

procedure DayTimeAdd(p1, p2, p3: PDayTime); //p3^:=p1^+p2^
var
 delta: integer;
begin;
 delta:=((p1.Lo xor p2.Lo xor (p1.Lo + p2.Lo + dtRest)) and dtCarry shr 4 + dtSergP) and dtRest;
 pInt64(p3)^:=delta + pInt64(p1)^ + pInt64(p2)^;
 end;

function DayTimeSub(p1, p2, p3: PDayTime): boolean; //p3^:=abs(p1^-p2^); result:=(p1>=p2)
begin;
 if pInt64(p1)^ >= pInt64(p2)^ then begin;
   pInt64(p3)^:=-(((p1.Lo xor p2.Lo xor (p1.Lo - p2.Lo)) and dtCarry shr 4 + dtSergP) and dtRest) + pInt64(p1)^ - pInt64(p2)^;
   Result:=true;
   end
 else begin; //p1^ < p2^
   pInt64(p3)^:=-(((p1.Lo xor p2.Lo xor (p2.Lo - p1.Lo)) and dtCarry shr 4 + dtSergP) and dtRest) + pInt64(p2)^ - pInt64(p1)^;
   Result:=false;
   end;
 end;


Результирующий ассемблерный код получился довольно эффективным.

> Dennis I. Komarov ©   (15.08.15 21:37) [3]
> это еще и валидность значения каждый раз проверять надо...

Зачем проверять? Оно всегда валидно, если не портить.
Для пущей красивости можно добавить функции вроде IncDayTimeBySeconds.


 
SergP ©   (2015-08-17 18:07) [26]


> Результирующий ассемблерный код получился довольно эффективным.


К сожалению почти никогда не интересовался эффективностью кода, который создает компилятор. Посему может и фигню спрошу,
но точки зрения эффективности не будет ли такое лучше: (типа на 1 операцию меньше) ?

procedure DayTimeAdd(p1, p2, p3: PDayTime); //p3^:=p1^+p2^
var
 delta: integer;
begin;
 pInt64(p3)^:= pInt64(p1)^ + pInt64(p2)^;
 delta:=((p1.Lo xor p2.Lo xor (p3.Lo + dtRest)) and dtCarry shr 4 + dtSergP) and dtRest;
 Inc(pInt64(p3)^,delta);
end;


 
Sha ©   (2015-08-17 18:33) [27]

> SergP ©   (17.08.15 18:07) [26]

Думаю, что будет примерно одинаково, т.к. в обоих случаях мы имеем цепочку последовательных зависимых вычислений. Хотя я склоняюсь к первому варианту, т.к. он меньше изменяет память и короче (количество ассемблерных инструкций 11+8<12+10+4).


 
SergP ©   (2015-08-17 19:01) [28]

Хм. А почeму это:
pInt64(p3)^:=delta + pInt64(p1)^ + pInt64(p2)^;    8 инструкций
а
pInt64(p3)^:= pInt64(p1)^ + pInt64(p2)^; 12 инструкций

?


 
NoUser ©   (2015-08-17 19:12) [29]

сложение не прошло тест - пока только вычитание
const
cSm = $3F;
cMm = $0FC0;
cHm = $0001F000;

cSa = $04;
cMa = $0100;
cHa = $8000;

cSx = $3B;
cMx = $0EC0;
cHx = $00017000;

function DayTimeSub(a, b, c :PDayTime) :Boolean;
begin
if ( a^ >= b^ ) then
 begin
  c^ := a^ - b^;
  if ( ((c^ and cSm) > cSx) or ( (a^ and cSm) < (b^ and cSm) ) ) then Dec(c^, cSa);
  if ( ((c^ and cMm) > cMx) or ( (a^ and cMm) < (b^ and cMm) ) ) then Dec(c^, cMa);
  if ( ((c^ and cHm) > cHx) or ( (a^ and cHm) < (b^ and cHm) ) ) then Dec(c^, cHa);
  Result :=  True ;
 end
else Result :=( not DayTimeSub(b, a, c) );
end;


 
Sha ©   (2015-08-17 19:13) [30]

> SergP ©   (17.08.15 19:01) [28]

это оптимизатор чудит, по идее там достаточно 6, а не 12 инструкций


 
Sha ©   (2015-08-17 19:20) [31]

> NoUser ©   (17.08.15 19:12) [29]

а будет ли разность вычислена правильно,
если ее адрес совпадает с адресом уменьшаемого или вычитаемого?


 
Sha ©   (2015-08-17 20:58) [32]

>NoUser ©   (17.08.15 19:12) [29]

усилил тест дополнительными проверками


procedure TForm1.Button4Click(Sender: TObject);
var
 d1, h1, m1, s1: integer;
 d2, h2, m2, s2: integer;
 d3, h3, m3, s3: integer;
 i1, i2: integer;
 t1, t2, t3: integer;
 v1, v2, v3: integer;
 x1, x2, x3: int64;
 error: integer;
 res: boolean;
begin;
 for i1:=0 to $1FFF do begin;
   d1:=i1 shr 12;                               t1:=d1 shl 17;       v1:=     d1 * (60*60*24);
   h1:=i1 shr 8 and 15; h1:=h1 + h1 and 8;      t1:=t1 or h1 shl 12; v1:=v1 + h1 * (60*60);
   m1:=i1 shr 4 and 15; if m1>7 then m1:=m1+44; t1:=t1 or m1 shl 6;  v1:=v1 + m1 * 60;
   s1:=i1       and 15; if s1>7 then s1:=s1+44; t1:=t1 or s1;        v1:=v1 + s1;

   for i2:=0 to $1FFF do begin;
     d2:=i2 shr 12;                               t2:=d2 shl 17;       v2:=     d2 * (60*60*24);
     h2:=i2 shr 8 and 15; h2:=h2 + h2 and 8;      t2:=t2 or h2 shl 12; v2:=v2 + h2 * (60*60);
     m2:=i2 shr 4 and 15; if m2>7 then m2:=m2+44; t2:=t2 or m2 shl 6;  v2:=v2 + m2 * 60;
     s2:=i2       and 15; if s2>7 then s2:=s2+44; t2:=t2 or s2;        v2:=v2 + s2;

     x1:=t1;
     x2:=t2;
     res:=DayTimeSub(@x1, @x2, @x3);
     t3:=x3;

     d3:=t3 shr 17;         v3:=     d3 * (60*60*24);
     h3:=t3 shr 12 and $1f; v3:=v3 + h3 * (60*60);
     m3:=t3 shr 6 and $3f;  v3:=v3 + m3 * 60;
     s3:=t3 and $3f;        v3:=v3 + s3;

     error:=0;
     if (res<>(v1>=v2)) or (v3<>abs(v1-v2)) or (h3>=24) or (m3>=60) or (s3>=60)
     then error:=3
     else begin;
       x1:=t1;
       x2:=t2;
       if (res<>DayTimeSub(@x1, @x2, @x2)) or (x3<>x2) then begin;
         x3:=x2;
         error:=2;
         end
       else begin;
         x1:=t1;
         x2:=t2;
         if (res<>DayTimeSub(@x1, @x2, @x1)) or (x3<>x1) then begin;
           x3:=x1;
           error:=1;
           end;
         end;
       if error<>0 then begin;
         t3:=x3;
         d3:=t3 shr 17;
         h3:=t3 shr 12 and $1f;
         m3:=t3 shr 6 and $3f;
         s3:=t3 and $3f;
         end;
       end;

     if error<>0 then begin;
       Memo1.Lines.Add(Format("%d %d %d %d",[d1,h1,m1,s1]));
       Memo1.Lines.Add(Format("%d %d %d %d",[d2,h2,m2,s2]));
       Memo1.Lines.Add(Format("%d %d %d %d",[d3,h3,m3,s3]));
       Memo1.Lines.Add(Format("failed %d",[error]));
       exit;
       end;

     end;
   end;

 Memo1.Lines.Add("done")
 end;


после этого DayTimeSubNoUser проваливает тест:
0 0 0 1
0 0 0 1
32767 23 59 60
failed 1


 
NoUser ©   (2015-08-17 23:05) [33]

> после этого DayTimeSubNoUser проваливает тест:
Значит DayTimeSubNoUser было тестом для теста ))


 
SergP ©   (2015-08-18 05:10) [34]


> Sha ©   (17.08.15 19:13) [30]
>
> > SergP ©   (17.08.15 19:01) [28]
>
> это оптимизатор чудит, по идее там достаточно 6, а не 12
> инструкций


вот, кстати интересно, а как компилятор соптимизирует такое:

a:=b-c;
if a=0 then ...

по идее после a:=b-c операцию сравнения не нужно делать, ибо флаги и так будут выставленны должным образом...


 
Sha ©   (2015-08-18 10:11) [35]

> SergP ©   (18.08.15 05:10) [34]

насколько знаю, Delphi сравнивает


 
DayGaykin ©   (2015-08-18 16:43) [36]


> вместо замечательного типа TDateTime

Как по моему, так не очень и замечательный.


 
Sha ©   (2015-08-19 01:04) [37]

Нашел один вариант решения:

const
 dtCarry = $00021040;
 dtMagic = 8667136;
 dtDeltas: array[0..7] of integer= (0, $4, $100, $104, $8000, $8004, $8100, $8104);

procedure DayTimeAdd(p1, p2, p3: PDayTime); //p3^:=p1^+p2^
var
 delta: integer;
begin;
 delta:=dtDeltas[(p1.Lo xor p2.Lo xor (p1.Lo + p2.Lo + dtRest)) and dtCarry * dtMagic shr 29];
 pInt64(p3)^:=delta + pInt64(p1)^ + pInt64(p2)^;
 end;


Замечательной особенностью этого варианта является то,
что он годится и для формата времени с миллисекундами,
меняется только магия.


 
SergP ©   (2015-08-20 09:33) [38]


> Sha ©   (19.08.15 01:04) [37]


Угу. Вроде так получается более универсально... Но первоначальному заданию не соответствует:


> Требуется без использования операций деления-умножения написать
> процедуры:


Кстати, давай еще какие-нить задачи-головоломки, а то в последние годы тут как-то скучновато.



Страницы: 1 вся ветка

Текущий архив: 2016.05.01;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.006 c
15-1440192604
Юрий
2015-08-22 00:30
2016.05.01
С днем рождения ! 22 августа 2015 суббота


15-1439244279
Германн
2015-08-11 01:04
2016.05.01
Футы и узлы в современной авиации.


2-1412527275
hook
2014-10-05 20:41
2016.05.01
hook на WM_Destroy


2-1411730430
Дмитрий
2014-09-26 15:20
2016.05.01
GridKeyUp и InputBox - застреваю при нажатии Ентера


15-1439415001
Юрий
2015-08-13 00:30
2016.05.01
С днем рождения ! 13 августа 2015 четверг