Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2016.07.24;
Скачать: [xml.tar.bz2];

Вниз

Суботняя головоломка от Розыча   Найти похожие ветки 

 
Rouse_ ©   (2015-08-22 12:24) [0]

Кстати вот вам еще одна задачка, автор не я:

"Для первого класса церковно-приходской школы.
Написать алгоритм, сравнивающий строку из двух символов на равенство "MZ" или "ZM", используя не более одного if (т.е. else if использовать нельзя)."

К примеру, перефразируя, пусть это будет функция в которую передается 2 симфола, которая должна вернуть True в случае если один из символов равен "M" а второй "Z" (порядок не важен).

function Check_IsMZorZM(A, B: AnsiChar): Boolean;
begin
//код писать здесь...
end;


Мой вариант решения был в 9 строчек ASM кода, впрочем не обязательно писать на ассемблере :)

ЗЫ: поясню, вот написать нельзя:

function Check_IsMZorZM2(A, B: AnsiChar): Boolean;
begin
Result := ((A = "M") and (B = "Z") ) or ((A = "Z") and (B = "M"));
end;


ибо тут будет 4 сравнения:

cmp al, $4D
jnz 5
cmp dl, $5A
Jz $C
cmp al, $5A
jnz 5
cmp dl, $4D
jz 3
xor eax, eax
ret
mov al, 1
ret


 
palva ©   (2015-08-22 13:56) [1]


{$APPTYPE CONSOLE}

function Check_IsMZorZM(A, B: AnsiChar): Boolean;
var
   x,y,t: Integer;
begin
//код писать здесь...
   x := ord(A);
   y := ord(B);
   t := (x+y)*256 + abs(x-y);
   Result := t = 42765;
end;

begin
 WriteLn(Check_IsMZorZM("M","Z"));
 WriteLn(Check_IsMZorZM("Z","M"));
 WriteLn(Check_IsMZorZM("N","Y"));
end.


 
Rouse_ ©   (2015-08-22 14:02) [2]


> palva ©   (22.08.15 13:56) [1]

Правильно, можно немного подоптимизировать, но правильно.


 
DayGaykin ©   (2015-08-22 15:42) [3]

Не интересно. Давай-те вообще без сравнений!


 
Sha ©   (2015-08-22 15:43) [4]

> Rouse_ ©   (22.08.15 12:24)

Их море, не считая банальной a*a+b*b.  
Например, среди таких (a op1 c) op2 (b op1 c),
где c - константа, а (op1, op2) = (*, xor), (*, or), (+, *), (xor, *).


 
Rouse_ ©   (2015-08-22 15:57) [5]


> DayGaykin ©   (22.08.15 15:42) [3]
> Не интересно. Давай-те вообще без сравнений!

Напиши


 
Rouse_ ©   (2015-08-22 16:00) [6]


> Sha ©   (22.08.15 15:43) [4]

IMUl + SUB - будут коллизии


 
Rouse_ ©   (2015-08-22 16:01) [7]

ЗЫ: хоть решение уже и показано - но оно не самое эффективное.
Можно проще.


 
DayGaykin ©   (2015-08-22 16:01) [8]

Я ASM не знаю. Дай мне немного времени.


 
Sha ©   (2015-08-22 16:02) [9]

Вот это мне нравится

(4*a+b+115) or (4*b+a+115)=553


 
Sha ©   (2015-08-22 16:04) [10]

> Rouse_ ©   (22.08.15 16:00) [6]
> IMUl + SUB - будут коллизии

Не всегда.
Если сюда писать начну все те, что без коллизий, места не хватит )


 
DayGaykin ©   (2015-08-22 16:10) [11]


> Sha ©   (22.08.15 16:02) [9]

Я короче нашел. (X+101) * (Y+101) = 33998


 
Sha ©   (2015-08-22 16:15) [12]

> DayGaykin ©   (22.08.15 16:10) [11]

В [4] еще куча таких коротких. Но и там, и у тебя есть умножение.
А в [9] умножения нет )


 
DayGaykin ©   (2015-08-22 16:20) [13]

function Check_IsMZorZM2(A, B: Byte): Boolean;
asm
 add al, $65
 add dl, $65
 mul dl
 xor ax, $84CE
 jz @x
 mov ax, 1
@x:
 not ax
 and eax, 1
end;



> Sha ©   (22.08.15 16:15) [12]

Умножение так страшно?


 
Sha ©   (2015-08-22 16:21) [14]

> DayGaykin ©   (22.08.15 16:10) [11]

Кстати, там есть константы и поменьше, например (X+77) * (Y+77) = 25718


 
Sha ©   (2015-08-22 16:24) [15]

> DayGaykin ©   (22.08.15 16:20) [13]
> Умножение так страшно?

Нет, сейчас не страшно уже. Это раньше было.


 
DayGaykin ©   (2015-08-22 16:29) [16]


> Кстати, там есть константы и поменьше, например (X+77) *
> (Y+77) = 25718

Я подобрал методом "тыка". Мне сразу повезло со 101 :)

Как в EAX положить значение флагового регистра?


 
Sha ©   (2015-08-22 16:36) [17]

Result:=((X+101) * (Y+101) = 33998)


 
Rouse_ ©   (2015-08-22 16:40) [18]


> DayGaykin ©   (22.08.15 16:20) [13]

Вах, даже красивее чем у меня :)
Правда чутка помедленней (разучились процессоры эффективно с 8-битными L/H работать, просадочка будет небольшая, но красивее)

Вот мой вариант:


> function Check_IsMZorZM(A, B: AnsiChar): Boolean;
> asm
>   and eax, $FF
>   and edx, $FF
>   mov ecx, eax
>   xor ecx, edx
>   sub ecx, $17
>   imul edx
>   lea ecx, [eax + ecx - $1B12]
>   cmp ecx, 0
>   setz al
> end;


зы:

> Как в EAX положить значение флагового регистра?

Через setz после компарации.


 
DayGaykin ©   (2015-08-22 16:42) [19]

Про SETZ не нашел. Нашел LAHF. Получилось вот так:

function Check_IsMZorZM2(A, B: Byte): Boolean;
asm
 add al, $65
 add dl, $65
 mul dl
 xor ax, $84CE
 lahf
 and eax, $4000 // ZF
 shr eax, 14
end;

Сравнение, конечно, все-равно осталось.


 
Rouse_ ©   (2015-08-22 16:43) [20]


> Sha ©   (22.08.15 16:02) [9]
> Вот это мне нравится
>
> (4*a+b+115) or (4*b+a+115)=553

Да, естественно это тоже верно (кто бы сомневался :)


 
DayGaykin ©   (2015-08-22 16:44) [21]

С твоими задачами я скоро ASM начну понимать :)


 
Rouse_ ©   (2015-08-22 16:44) [22]


> DayGaykin ©   (22.08.15 16:42) [19]

Мдя, пошел пить коньяк и посыпать голову пеплом - молоток :)


 
Rouse_ ©   (2015-08-22 16:50) [23]


> DayGaykin ©   (22.08.15 16:44) [21]

Блин, этож Дима :))
Я то думаю кто это такой хитрый на форуме появился :)))


 
DayGaykin ©   (2015-08-22 17:06) [24]

С SETZ интереснее, да:
function Check_IsMZorZM2(A, B: AnsiChar): boolean;
asm
 add al, $65
 add dl, $65
 mul dl
 xor ax, $84CE
 setz al
end;



> Блин, этож Дима :))
> Я то думаю кто это такой хитрый на форуме появился :)))

С тем ником, видимо, покончено :)


 
Rouse_ ©   (2015-08-22 17:14) [25]


> DayGaykin ©   (22.08.15 17:06) [24]

Ты победил :))


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

> Rouse_ ©   (22.08.15 17:14) [25]

и не он один, см. [4] )


 
Rouse_ ©   (2015-08-22 17:35) [27]

Саш, ну я тебя никогда не считал - бо с твоей квалификацией... :)


 
SergP ©   (2015-08-24 19:06) [28]

Попробовал обойтись без умножения... Правда кол-во инструкций на 1 больше чем [24]

function Check_IsMZorZM_SergP(A, B: AnsiChar): boolean;
asm
mov ah,dl
sub ax,$53d4
sbb dx,dx
xor ax,dx
cmp ax,$679
setz al
end;


 
Rouse_ ©   (2015-08-24 19:29) [29]


> SergP ©   (24.08.15 19:06) [28]

Угу, оно


 
Sha ©   (2015-08-24 19:46) [30]

не совсем "угу"


 
SergP ©   (2015-08-24 19:51) [31]


> DayGaykin ©   (22.08.15 16:29) [16]
>
>
> > Кстати, там есть константы и поменьше, например (X+77)
> *
> > (Y+77) = 25718
>
> Я подобрал методом "тыка". Мне сразу повезло со 101 :)


для подбора константы ИМХО чисто теоретически достаточно чтобы t+$4d или t+$5a было простым числом, большим чем 128
ближайшее к 128 и большее него простое число 131, так что похоже что минимальная константа будет 131-$5a=41


 
Rouse_ ©   (2015-08-24 19:51) [32]


> Sha ©   (24.08.15 19:46) [30]
> не совсем "угу"

На моих тестах от нуля до 255 прошла по обоим чарам, что я упустил?


 
SergP ©   (2015-08-24 19:52) [33]


> Sha ©   (24.08.15 19:46) [30]
>
> не совсем "угу"


что там не то?


 
Sha ©   (2015-08-24 19:54) [34]

хотя нет, наверно, "угу", надо проверить...


 
SergP ©   (2015-08-24 20:00) [35]

Я проверял:

procedure TForm1.Button1Click(Sender: TObject);
var
x,y:byte;
begin
 for x:=0 to 255 do
   for y:=0 to 255 do
     if Check_IsMZorZM_Sergp(ansichar(x),ansichar(y)) then Memo1.
Lines.Add(IntToHex(y*256+x,4));
end;


ИМХО единственное " не совсем" может заключатся в том что результат
setz al
возможно не совсем соответствует boolean


 
Rouse_ ©   (2015-08-24 20:03) [36]


> возможно не совсем соответствует boolean

Соответствует.


 
SergP ©   (2015-08-24 20:11) [37]


> Rouse_ ©   (24.08.15 20:03) [36]
>
>
> > возможно не совсем соответствует boolean
>
> Соответствует.


хз. я ассемблера не знаю.  Просто в инете полазил и прочитал что setz al делает al=1 если установлен флаг нуля, но по идее для boolean оно должно быть не 1, а $FF , хотя мож я чего-то и забыл уже...


 
Rouse_ ©   (2015-08-24 20:14) [38]


> SergP ©   (24.08.15 20:11) [37]

Три разных нотации BOOL, Boolean и первый бит.


 
SergP ©   (2015-08-24 20:47) [39]

кстати, вопрос по ассемблеру:
можно ли использовать старшие слова регистров EAX, EBX, ECX, EDX в качестве операндов? если да, то как?


 
Игорь Шевченко ©   (2015-08-24 21:08) [40]


> можно ли использовать старшие слова регистров EAX, EBX,
> ECX, EDX в качестве операндов?


нет



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

Форум: "Прочее";
Текущий архив: 2016.07.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.01 c
15-1445778899
pavelnk
2015-10-25 16:14
2016.07.24
SEO странность


2-1416740909
Banana
2014-11-23 14:08
2016.07.24
Delphi 7 Юникод на печать


15-1440235442
Rouse_
2015-08-22 12:24
2016.07.24
Суботняя головоломка от Розыча


15-1442261724
Pavia
2015-09-14 23:15
2016.07.24
Определения.


15-1445808604
Юрий
2015-10-26 00:30
2016.07.24
С днем рождения ! 26 октября 2015 понедельник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский