Мелкие задачки для крупных мозгов №21

Тема в разделе "WASM.A&O", создана пользователем The Svin, 10 май 2006.

  1. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    пусть число a - количество элементов в массиве

    b - отрицательное число, абсолютное значение которого означает сколько в массиве отрицательных чисел.

    Мы должны вернуть через a

    0 если отрицательных и положительных чисел поровну

    1 если больше отрицательных чисел

    2 если больше положительных.

    Пример:

    1)

    a = 21

    b = -7

    тогда отрицательных 7 и положительных 14

    мы возвращаем a = 2

    2)

    a = 10

    b = -5

    мы возвращаем а = 0

    3)

    a = 15

    b = -10

    мы возвращаем 1



    Оптимизация по размеру. Безбранчевый код.

    Операнды целочисленные 32х разрядные.
     
  2. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    ну давайте я дам для затравки какой-нить простой вариант.

    например:
    Код (Text):
    1.  
    2. ; a = eax
    3. ; b = ebx
    4. ;строим по флагам результата ? a - |2b|
    5.  shl ebx,1
    6.  add eax,ebx
    7.  lahf
    8.  shr eax,14
    9.  add eax,3
    10.  and eax,3
    11.  shr eax,1
    12.  adc eax,0
    13.  
     
  3. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Код (Text):
    1. ; a = eax
    2. ; b = ebx
    3. lea     eax, [eax+ebx*2]
    4. xor     ebx, ebx
    5. neg     eax
    6. adc     ebx, 0
    7. shl     eax, 1
    8. adc     ebx, 0
    9. xchg    eax, ebx




    на 3 байта короче, и вроде правильно :)
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine


    Если поменять {0, 1, 2} на {0, -1, 1}, то укладывается в 10 байт и не затирается ebx:
    Код (Text):
    1. add eax,ebx
    2. add eax,ebx
    3. cdq
    4. neg eax
    5. adc edx,edx
    6. xchg eax,edx


    Добавил: lea eax,[eax+ebx*2] на 1 байт короче 2х add.
     
  5. your_enemy

    your_enemy New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2003
    Сообщения:
    9
    eax<-a, ebx<-b, ecx<-0, в cl - результат. Я понимаю, что написано криво (нет практики), но просто надоело уже проходить мимо...мне итак это далось с большими мучениями
    Код (Text):
    1.  
    2. add   eax,ebx
    3. neg   ebx
    4. cmp   eax,ebx
    5. lahf
    6. mov   ch,ah
    7. shr   cx,14
    8. xor   cl,00000010b
    9. sub   cl,2
    10. lahf
    11. mov   ch,ah
    12. shr   cx,14
    13.  
     
  6. your_enemy

    your_enemy New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2003
    Сообщения:
    9
    блин, пока писал, здесь уже столько красивых вариантов... лучше бы я не позорился
     
  7. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Незя! :)
     
  8. AlB80

    AlB80 New Member

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    25
    Адрес:
    Russia
    Если еще немножко дооптимизировать по размеру,



    ; a = eax

    ; b = ebx

    lea ebx, [eax+ebx*2]

    xor eax, eax

    neg ebx

    adc eax, eax

    shl ebx, 1

    adc eax, 0



    то можно сэкономить еще 2 байта. Один на adc, второй на xchg.
     
  9. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    your_enemy



    Чушь. Пиши и не думай о такой фигне :) Чем больше материала почитать\понять\посчитать - тем лучше.
     
  10. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine


    Та я знаю что автор специально подобрал такие коэффициенты, чтобы нельзя было просто решить, но мне тоже надоело проходить мимо :) А то потом придёт BlackMirror и постить что-либо после него смысла уже не будет ;)



    ЗЫ: А что если сделать отдельную задачу: {0, 1, 2} преобразовать в {0, -1, 1} и/или обратно?
     
  11. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Вообще-то задачки я даю как кусочки из реальной практики.

    Т.е. можно быть уверенным что где-то именно нужно было получить 0,1,2 и изменение на 0,-1,1 привело бы к резкому ухудшению по всему связанному с этим значением коду.

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

    А насчёт Чёрного Зеркала, его боятся нечего - думаю, что он сам внимательно просматривает код и подмечает для себя интересные приёмы \ закономерности. Чего вобщем нам всем стоит придерживаться. Единственный смысл - разобраться в задачах повнимательней и поучится друг у друга. Я так думаю.
     
  12. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Мне почему-то кажется что из этих 12 байт как минимум один лишний, только я его еще не нашел.


    Код (Text):
    1.     lea eax,[eax+ebx*2]
    2.     neg eax
    3.     cdq
    4.     sbb edx,0
    5.     neg edx
    6.     xchg eax,edx
     
  13. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Эхх... Чуть-чуть не успел :dntknw:
    Код (Text):
    1. lea eax,[eax+ebx*2]
    2. neg eax
    3. cdq
    4. not edx
    5. adc edx,1
    6. xchg eax,edx
     
  14. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    На всякий случай выложу ещё один вариант. Попытался решить другим путём, но размер получился 14 байт:
    Код (Text):
    1. lea edx,[eax+ebx*2]
    2. xor eax,eax
    3. neg edx
    4. adc eax,eax
    5. shl edx,1
    6. adc eax,0
     
  15. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Код (Text):
    1. lea eax,[eax+ebx*2]
    2. cdq
    3. cmp edx,eax
    4. rcr eax,1
    5. shr eax,30
     
  16. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Молодец,leo

    Я почему то думал, что этот приём (cdq,cmp edx,eax) будет использовать Black_mirror. В предыдущих задачах он использовался очень элегантно.
     
  17. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    The Svin

    Тут наверное, дело не столько в cdq+cmp, т.к. это лишь способ установки CF при eax > 0 и использовать его можно по разному. Возможно мы просто увлеклись использованием adc\sbb и стали забывать о существовании rcr\rcl и lahf\pushfd (может и bt пригодились бы, только размерчик великоват :). А в данном случае как раз rcr неплохо вписалась в сочетании с элегантным приемчиком c cdq+cmp. Где-то возможно и lahf\pushfd "впишутся"