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

Вниз

Пятничная задачка   Найти похожие ветки 

 
MBo ©   (2009-09-11 08:45) [0]

Васе Пупкину нужно написать функцию, которая возвращает количество числовых палиндромов от 1 до заданного натурального числа включительно. Число называется палиндромом, если его десятичная запись читается одинаково слева направо и справа налево, например, 53235.
прототип
function PalindromeCount(const N:Int64): Int64;
например, для N = 101 результат -  19 (1..9, 11, 22..99, 101)
Как Васе сделать это наиболее эффективно?


 
Sergey Masloff   (2009-09-11 09:59) [1]

Смотря что понимать под эффективностью ;-)
Если минимальные затраты дорогостоящего труда программиста то можно тупо переворачивать строковое представление и сравнивать на равенство.

Я сам помнится будучи васей пупкиным решал это задание на 1 курсе института (строки перворачивать было нельзя)


 
Дмитрий С ©   (2009-09-11 10:02) [2]


> Sergey Masloff   (11.09.09 09:59) [1]

Ну можно и палиндромы перебрать по формулам типа:
a
a+10b
a+10b+100a
...
И посчитать их количество до заданного.
Интересно, математически наверняка можно решить :)


 
Павел Калугин ©   (2009-09-11 10:02) [3]

> [1] Sergey Masloff   (11.09.09 09:59)
> (строки перворачивать было нельзя)

Сравнивали разряды в первой и последней позиции, второй и предпоследней и так далее?


 
Павел Калугин ©   (2009-09-11 10:03) [4]

> [2] Дмитрий С ©   (11.09.09 10:02)
> a
> a+10b
> a+10b+100a

тогда уж
a+10a


 
Чесслово   (2009-09-11 10:20) [5]

>Васе Пупкину нужно написать функцию...
>Как Васе сделать это наиболее эффективно?
Спросить на форуме


 
Alx2 ©   (2009-09-11 10:29) [6]

Гады... У меня работы полно, а тут - задачка. :)


 
Дуб ©   (2009-09-11 10:34) [7]

> Alx2 ©   (11.09.09 10:29) [6]

Для 10 в степени - ответ выписывается сразу. А вот для тех, что от ближайшей степени до числа - уже интереснее.


 
Alx2 ©   (2009-09-11 10:45) [8]

> Дуб ©   (11.09.09 10:34) [7]

Я пока навскидку смотрю как на количество целочисленных точек, которые сидят на "палиндромной" плоскости, соответствующим образом ограниченной. Т.е. как на кол-во решений некоторого диофантова уравнения. Оно обычно быстро может быть подсчитано. Но серьезно туда думать - никак :)


 
Дуб ©   (2009-09-11 11:30) [9]

> Alx2 ©   (11.09.09 10:45) [8]

При дамах попрошу не выражаться. У меня вышло довольно просто все.


 
Alx2 ©   (2009-09-11 11:59) [10]

>Дуб ©   (11.09.09 11:30) [9]

Хм... да, ты прав. Я загнался. Нашел как сделать значительно проще.


 
Дмитрий С ©   (2009-09-11 13:06) [11]

Идеи то какие?
У меня идея такая:
1. Находим по формуле количество палиндромов для ближайшей степени двойки:

Например, для числа 5"345"232 это будет 1"000"000

2. Прибавляем к нему число оставшихся палиндромов, путем отбрасывания половины знаков:

Например, для 5"345"232 нужно прибавить: 5"345

3. Компенсировать неточность предыдущего этапа.


 
Дуб ©   (2009-09-11 13:11) [12]

> 1. Находим по формуле количество палиндромов для ближайшей
> степени двойки:

десятки

> 2. Прибавляем к нему число оставшихся палиндромов, путем
> отбрасывания половины знаков:

Для четного числа знаков так. Для нечетного чуть сложнее.

> 3. Компенсировать неточность предыдущего этапа.

так, да.


 
Дмитрий С ©   (2009-09-11 13:12) [13]

В первом пункте обозначена ближайшая степень двойки, а число палиндромов находится по формуле: S(X).

 function O(X: Int64): Int64; inline;
 begin
   Result := Round(Power(10, (X+1) div 2) - 1) div 9;
 end;
 function S(X: Int64): Int64; inline;
 begin
   Result := 18*(O(X) - (X mod 2)*5*Round(Power(10, X div 2 - 1)));
 end;


 
Дмитрий С ©   (2009-09-11 13:13) [14]

десятки, точно.


 
Дуб ©   (2009-09-11 13:13) [15]


> Для четного числа знаков так. Для нечетного чуть сложнее

и отнять надо еще, степень десятки.


 
Дмитрий С ©   (2009-09-11 13:16) [16]

Блин, забыл уточнить.
S(X), тут X - это количество знаков в числе


 
MBo ©   (2009-09-11 15:07) [17]

>Дмитрий С ©   (11.09.09 13:12) [13]
что-то я запутался в X-ах, где что обозначает


 
Омлет   (2009-09-11 15:19) [18]

Для степеней десятки можно ускорить :)

const
 Power10_PaliCount: array [1..18] of Integer =
   (9,18,108,198,1098,1998,10998,19998,109998,199998,1099998,1999998,10999998,
    19999998,109999998,199999998,1099999998,1999999998);

 if N > 9 then
 begin
   Len := Ceil(Log10(N + 1)); // Число разрядов
   Result := Power10_PaliCount[Len-1];
 end

Дальше сложнее.. Надо рекурсивно что ли разряды уменьшать..


 
Омлет   (2009-09-11 15:32) [19]

Или рекурсивно спускаться, уменьшая порядок числа, прибавляя по 9*(10^X), где X = Len div 2.
Но нужно еще как-то при этом учитывать остаток.


 
oldman ©   (2009-09-11 17:11) [20]


> Васе Пупкину нужно написать функцию, которая возвращает
> количество числовых палиндромов от 1 до заданного натурального
> числа включительно.


Например, в заданном числе N разрядов.
Числа a в виде "сс" (где с меняется от 1 до b=половина разрядов N), будут палиндромами

Например, N=16 (2 разряда)
b должно иметь один разряд (от 1 до 9)
Палиндромы для a от 1 до 9:
11
(22>N)

Надеюсь, идея понятна... (Васе пупкину не забыть про нечетное количество разрядов!!!)

Для N=1234 палиндромы:
1
2
3
4
5
6
7
8
9
11
22
33
44
55
66
77
88
99
111
121
131
...
999
1001
1111
1221


 
Дуб ©   (2009-09-11 17:24) [21]

> MBo ©   (11.09.09 15:07) [17]

Там сложно. Но ты именно то, что в итоге описано подразумевал?

Или за пазухой бомбу держишь?


 
MBo ©   (2009-09-11 20:06) [22]

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

Ну я мог и ничего не подразумевать, а просто любопытствовать ;)

[13] мне непонятно, а подход [11] - понятен. Однако дьявол может скрываться в деталях- это насчет компенсации неточностей.


 
Дуб ©   (2009-09-12 04:37) [23]

> MBo ©   (11.09.09 20:06) [22]

Ну да, пункт 3 очень широк. :)

Я на тройке примеров распишу как считается:

1. 5345236 F = 6343

F = 999 + 999 + (534-100)*10 + 6 -1

2.  5345532 F = 6344

F = 999 + 999 + (534-100)*10 + 6

3.  534527 F = 1533

F = 999 + 99 + 535-100

3.  534227 F = 1532

F = 999 + 99 + 535-100 -1


 
Омлет   (2009-09-13 21:24) [24]

Примерное решение
http://mathworld.wolfram.com/PalindromicNumber.html


 
Achpile   (2009-09-14 14:47) [25]

Надо заметить, что для любого четного числа разрядов кол-во полиномов равно кол-ву полиномов для предшествующего нечетного...

f(1) = 9
f(2) = 9
f(3) = 9 * 10
f(4) = 9 * 10
f(5) = 9 * 10 * 10 и т.д.

т.е.

f(x) = 9 * 10^((x - 1) div 2)

N"грубое" = E(i = 1 to n-1) f(i)

N"грубое" - число полиномов без учета сравнения с заданным
E - сумма
n - число разрядов заданного числа

Далее изучаем цифры в разрядах:

первая цифра a, для нее полиномов существует (a-1)*f(n-2)
вторая цифра b, для нее прибавляем (b-1)*f(n-4)

и так продолжаем до (n div 2) разряда.


 
Achpile   (2009-09-14 14:48) [26]

и еще + 1 для числа 0


 
SP   (2009-09-14 17:41) [27]

Хм... Все бы получалось довольно просто, типа так:

function PalindromeCount(const N:Int64): Int64;
var
 l,i:integer;
 t,v:int64;
begin
 l:=trunc(Log10(N))+1;
 result:=0;
 t:=1;
 v:=1;
 for i:=1 to l-1 do
 begin
   result:=result+t*9;
   if odd(i) then v:=v*10 else t:=t*10;
 end;
 result:=result+(N div t)-v+1;
end;


вот только проблема с определением не является ли последнее число палиндромом, поэтому указанная ф-ция не всегда правильно работает.
например для числа 1000 кол-во палиндромов должно быть на 1 меньше чем для числа 1001
Но не могу пока для этого написать компактный код


 
SP   (2009-09-14 18:32) [28]

ну можно так написать:
function PalindromeCount(const N:Int64): Int64;
var
 l,i:integer;
 t,v:int64;
 a,b,k:integer;
 p,q,y:int64;
begin
 l:=trunc(Log10(N))+1;
 result:=0;
 t:=1;
 v:=1;
 for i:=1 to l-1 do
 begin
   result:=result+t*9;
   if odd(i) then v:=v*10 else t:=t*10;
 end;
 y:=t*v;
 k:=1;
 p:=N;
 q:=N;
 for i:=1 to trunc(l/2) do
 begin
   a:=p mod 10;
   p:=p div 10;
   b:=q div y;
   q:=q mod y;
   y:=y div 10;
   if a>b then k:=1;
   if a<b then k:=0
 end;
 result:=result+(N div t)-v+k;
end;


только как-то не совсем красиво получается...


 
MBo ©   (2009-09-14 18:34) [29]

очень коротко и красиво, наверно, не получится.


 
SP   (2009-09-14 18:58) [30]

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


 
SP   (2009-09-14 21:04) [31]


> for i:=1 to trunc(l/2) do


м-да. глупость написал...

Лучше так

...
for i:=1 to l shr 1 do
...



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

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

Наверх




Память: 0.54 MB
Время: 0.013 c
2-1254305859
Fr
2009-09-30 14:17
2009.11.15
Кнопка в TWebBrowser


15-1253305803
Юрий
2009-09-19 00:30
2009.11.15
С днем рождения ! 19 сентября 2009 суббота


1-1223964035
jiny
2008-10-14 10:00
2009.11.15
TNTForm ; TWideCaption- не воспринимает казахский язык


2-1254209623
yantux
2009-09-29 11:33
2009.11.15
Повтороный выбор файла компонентом TOpenDialog


15-1253260563
usver
2009-09-18 11:56
2009.11.15
АСУС