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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.005 c
15-1248261640
@!!ex
2009-07-22 15:20
2009.11.15
Сколько вариантов чисел?


15-1253028542
TUser
2009-09-15 19:29
2009.11.15
Нет ли у кого-нибудь совсем старого железа?


15-1253392203
Юрий
2009-09-20 00:30
2009.11.15
С днем рождения ! 20 сентября 2009 воскресенье


15-1252644331
MBo
2009-09-11 08:45
2009.11.15
Пятничная задачка


2-1254289329
Johnnnnn
2009-09-30 09:42
2009.11.15
Управление с клавиатуры &amp;





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский