Программистская задачка
Feb. 27th, 2008 12:09 pmПостом Аввы навеяло.
Известна задача для интервью: написать int f(int x), которая для x==a возвращает b, а для x==b возвращает a. Один из вариантов ответа при данной спецификации: int f(int x) { return a+b-x; }
Напишите целое арифметико-логическое выражение (не использующее тернарного оператора и сравнений) с переменной х, которое для данных 32-битных целых a, b, c при x==a принимает значение b, при x==b - значение c, при x==c - значение a, в остальных случаях результат произволен. Для каких a, b, c решение существует?
Известна задача для интервью: написать int f(int x), которая для x==a возвращает b, а для x==b возвращает a. Один из вариантов ответа при данной спецификации: int f(int x) { return a+b-x; }
Напишите целое арифметико-логическое выражение (не использующее тернарного оператора и сравнений) с переменной х, которое для данных 32-битных целых a, b, c при x==a принимает значение b, при x==b - значение c, при x==c - значение a, в остальных случаях результат произволен. Для каких a, b, c решение существует?
no subject
Date: 2008-02-27 08:28 pm (UTC)no subject
Date: 2008-02-27 08:37 pm (UTC)no subject
Date: 2008-02-27 08:47 pm (UTC)no subject
Date: 2008-02-27 08:50 pm (UTC)no subject
Date: 2008-02-27 08:51 pm (UTC)no subject
Date: 2008-02-27 09:55 pm (UTC)no subject
Date: 2008-02-27 10:12 pm (UTC)no subject
Date: 2008-02-27 10:14 pm (UTC)no subject
Date: 2008-02-27 10:20 pm (UTC)делим 32 бит на 3 10-битовых поля и два старших бита оставляем неиспользованными.
В качестве операции делаем циклицеский сдвиг используемых 30 битов на 10 разрядов.
#define MASK ((1<<10)-1)
#define MASKHI ((MASK << 10)|(MASK << 20))
int f(int x) {
return ((x & MASK)<<20)
| ((x &MASKHI) >> 10);
}
Соответственно, a, b, и c - такие, которые можно представить этими сдвигами. Ну и, естественно, можно брать меньше 10 бит, и неиспользуемые биты раскидывать по числу произвольным образом, и сдвиги делать в разные стороны.
no subject
Date: 2008-02-27 10:52 pm (UTC)no subject
Date: 2008-02-27 11:12 pm (UTC)no subject
Date: 2008-02-27 11:14 pm (UTC)то что результат == 0 или 1 ?
Date: 2008-02-27 11:21 pm (UTC)(-(x==a))&b | (-(x==b))&c | (-(x==c))&a
Re: то что результат == 0 или 1 ?
Date: 2008-02-27 11:23 pm (UTC)Re: то что результат == 0 или 1 ?
Date: 2008-02-28 01:02 am (UTC)а сравнение с нулём - это -(x|(x<<1)|...|(x<<31))
Re: то что результат == 0 или 1 ?
Date: 2008-02-28 01:20 am (UTC)Вот
Date: 2008-02-28 01:30 am (UTC){
unsigned y=x^a;
y|=y<<1; y|=y<<2; y|=y<<4; y|=y<<8; y|=y<<16;
y|=y>>1; y|=y>>2; y|=y>>4; y|=y>>8; y|=y>>16; /* y=x==a ? 0 : 0xffffffff */
return b&~y;
}
unsigned f(unsigned x, unsigned a, unsigned b, unsigned c)
{
return change(x,a,b) | change(x,b,c) | change(x,c,a);
}
Re: Вот
Date: 2008-02-28 01:40 am (UTC)no subject
Date: 2008-02-28 05:59 am (UTC)no subject
Date: 2008-02-28 06:20 am (UTC)Re: Вот
Date: 2008-02-28 08:36 am (UTC)no subject
Date: 2008-02-28 10:08 am (UTC)Если два совпадают, решения нет.
Если все три совпадают, то просто x или a.
no subject
Date: 2008-02-28 10:28 am (UTC)no subject
Date: 2008-02-28 04:02 pm (UTC)Два числа совпадать не могут - этот случай противоречит условию.
no subject
Date: 2008-02-28 04:03 pm (UTC)Re: Вот
Date: 2008-02-28 06:58 pm (UTC)no subject
Date: 2008-02-28 08:21 pm (UTC)Тогда на всякий случай сделаем чистой арифметикой.
Пусть (unsigned)a < (unsigned)b < (unsigned)c (в остальных пяти случаях аналогично).
int f(int x)
{
unsigned ua = a;
unsigned ub = b;
unsigned uc = c;
unsigned ux = x;
unsigned mu = -1;
// начало места, зависящего от порядка между ua, ub, uc
// индикатор максимальной из трех точек
int ic = ux/uc;
// индикатор минимальной из трех точек
int ia = (mu - ux)/(mu - ua);
// индикатор оставшейся (средней) точки
int ib = 1 - ic - ia;
// конец особенного места
return ia*b + ib*c + ic*a;
}
no subject
Date: 2008-02-28 08:24 pm (UTC)no subject
Date: 2008-02-28 10:39 pm (UTC)no subject
Date: 2008-02-28 11:46 pm (UTC)b*(1+( ((x-a)|(a-x)) >> 31 )) +
c*(1+( ((x-b)|(b-x)) >> 31 )) +
a*(1+( ((x-c)|(c-x)) >> 31 ))
no subject
Date: 2008-02-28 11:59 pm (UTC)no subject
Date: 2008-02-29 02:18 am (UTC)Пусть p -- наименьшее простое число, на которое не делится (в обычном математическом смысле) ни одна из разностей a-b, a-c, b-c.
Оно не больше 79, так как произведение простых от 2 до 79 больше, чем 296.
Функция y(x) = ((x%p)+p)%p отобразит a, b, c в три разных числа A, B, C, лежащие в [0,p-1].
А дальше замечаем, что Zp -- поле, поэтому можно пользоваться интерполяционной формулой и построить три квадратных трехчлена PA(y), PB(y), PC(y), равных 1 (mod p) в одной из точек y=A, y=B, y=C, и 0 (mod p) в двух оставшихся. Коэффициенты можно, не ограничивая общности, брать из [0,p-1]. Тогда значения этих трехчленов (как обычные целые числа) на [0,p-1] будут лежать между 0 и (p-1)+(p-1)*(p-1)+(p-1)*(p-1)*(p-1), что с огромным запасом укладывается в диапазон представимых положительных чисел.
Далее стандартное разложение:
b*(PA(y(x))%p) + c*(PB(y(x))%p) + a*(PC(y(x))%p)
no subject
Date: 2008-02-29 02:52 am (UTC)no subject
Date: 2008-02-29 05:09 am (UTC)!x = (abs(x+1) + x + 1) * (abs(x-1) - x + 1) / 4
Если abs нельзя, то определим его как
abs(x) = x * sign(x), where
sign(x) = 1 & (x >>> 32)
no subject
Date: 2008-02-29 11:05 am (UTC)бессмысленное полурешение
Re: бессмысленное полурешение
Date: 2008-03-01 03:14 pm (UTC)Re: бессмысленное полурешение
Date: 2008-03-01 04:32 pm (UTC)no subject
Date: 2008-03-01 05:38 pm (UTC)no subject
Date: 2008-03-01 06:15 pm (UTC)no subject
Date: 2008-03-01 07:37 pm (UTC)Теперь медленно и аккуратно. Добавим к языку Си ещё одну операцию --- для двух неравных констант времени компиляции обозначим через х\у минимальное неотрицательное целое число, такое что (х-у)»(х\у) кончается на битик 1, то бишь является нечётным. Ну вот вроде и всё, осталось в формуле для Га заменить в числителе все выражения вида (х-б) на ((х-б)»(а\б)), да в знаменателе заменить (а-б) на ((а-б)»(а\б)) [ну и аналогично для остальных в,...,я вместо б]. Теперь в знаменателе стоит произведение нечётнных чисел, так что во всяком случае не ноль. Что происходит с числителем? Если он вычисляется с х=а, то он идентичен знаменателю, то есть сверху и снизу одинаковые ненулевые значения (пусть бы даже и настало переполнение), а если вычисляется с х=б или в,...,я, то числитель благополучно обнуляется.
Ну вот как-то так. Ну ещё конечно надо подуматть, как эту формулу быстро вычислить, банальное вычисление даёт О(м²), где «м» размер алфавита, то есть количество точек аппроксимации, но так как я не имею ни малейшего представления о конкретном применении, тут вам и карты в руки :-)
no subject
Date: 2008-03-01 07:48 pm (UTC)no subject
Date: 2008-03-01 07:49 pm (UTC)no subject
Date: 2008-03-01 08:49 pm (UTC)no subject
Date: 2008-03-01 09:36 pm (UTC)Памяти O(N), времени - константа, или, в случае строк, O(длина строки)