Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Русский_Проект: Изучение Visual Basic


Служба Рассылок Subscribe.Ru проекта Citycat.Ru
Русский_Проект: Рассылка Здравствуйте! Сегодняшний выпуск целиком посвящен разбору задачи о палиндромах. Я очень рад, что мое предложение о новой рубрике встретило горячий отклик. Я получил письма с просьбой продолжить это начинание. Спасибо всем!

Разбор полетов

Сначала напомню о задании. Определить, является ли введенная фраза палиндромом (т. е., читающейся задом наперед точно так же, например: "А роза упала на лапу Азора"). Никто не смог решить задачу с первого раза. Самая типичная ошибка - не учитывались знаки препинания. Я намеренно дал в качестве примера строчку без запятых. Искусство программирования заключается не только в том, чтобы решить задачу в частном случае, но и предугадать другие возможные варианты.
Отступление Некоторые выразили сомнения, что задача должна предусматривать знаки препинания. Ссылались на расплывчатось задания. Приводились разные аргументы. Например, присылались решения из разных олимпиад на паскале. Отвечаю. Мне олимпиады не указ. Там, в жюри тоже люди, которым свойственно ошибаться. Во-вторых, вы же пользуетесь интернетом. Воспользуйтесь любой поисковой системой и увидете гору ссылок на палиндромы. Просмотрите содержание - встречаются целые поэмы. Я приведу несколько красивых примеров палиндрома
На в лоб, болван!
Он дивен, палиндром, и ни морд, ни лап не видно...
О, вижу деву! Уведу живо!
Закопан, а попа напоказ
Яд, яд, дядя!.
Я иду с мечем, судия
Уведя лимузин, изумил я деву
Лена набила рожу мужу - муж орал и банан ел
Нежно теребя ртом сосок и косо смотря, берет он жен
Сон ведала - купил Егоров творог, ел и пукал Аде в нос
Нине: Леннон - не Ленин
На вид ангел, а лег на диван
Ссать любит, сев в вестибюль ТАСС
Да! Искать такси - ад!
Надеюсь, вопрос о запятых снят

Решение

Итак, теперь смысл решения ясен. Обработать строку, исключив все посторонние знаки и прочитать наоборот.
Первым, со второй попытки, решил задачу Виталий(vitarada@...)
Вот его решение
Option Explicit

' Добавте на форму два элемента Command1 и Text1

Private Sub Command1_Click()
Dim strPol As String

   strPol = Text1.Text

   ' убираем пробелы из строки
   strPol = dhTranslate(strPol, " ", "", False)

   ' сравниваем строку и ее реверс
   If StrComp(strPol, dhReverse(strPol), vbTextCompare) = 0 Then
      MsgBox "Фраза является палиндромом."
   Else
      MsgBox "Фраза не является палиндромом."
   End If
End Sub


Function dhTranslate(ByVal strIn As String, _
                     ByVal strMapIn As String, _
                     ByVal strMapOut As String, _
                     Optional fCaseSensitive As Boolean = True) As String
Dim intI As Integer
Dim intPos As Integer
Dim strChar As String * 1
Dim strOut As String
Dim intMode As Integer

   ' If there's no list of characters
   ' to replace, there's no point going on
   ' with the work in this function.
   If Len(strMapIn) > 0 Then
       ' Set up the comparison mode.
       If fCaseSensitive Then
           intMode = vbBinaryCompare
       Else
           intMode = vbTextCompare
       End If

       ' Right-fill the strMapOut set.
       If Len(strMapOut) > 0 Then
           strMapOut = Left$(strMapOut & String(Len(strMapIn), _
           Right$(strMapOut, 1)), Len(strMapIn))
       End If

       For intI = 1 To Len(strIn)
           strChar = Mid$(strIn, intI, 1)
           intPos = InStr(1, strMapIn, strChar, intMode)
           If intPos > 0 Then
               ' If strMapOut is empty, this doesn't fail,
               ' because Mid handles empty strings gracefully.
               strOut = strOut & Mid$(strMapOut, intPos, 1)
           Else
               strOut = strOut & strChar
           End If
       Next intI
   End If
   dhTranslate = strOut
End Function


Private Function dhReverse(ByVal strIn As String) As String
Dim abytIn() As Byte
Dim strTemp As String
Dim intI As Integer
Dim intMax As Integer
Dim bytTemp As Byte
Dim intNew As Integer

   If Len(strIn) = 0 Then
       dhReverse = strIn
   Else
       abytIn = strIn
       ' Now reverse all the characters.
       intMax = UBound(abytIn)

       For intI = LBound(abytIn) To (intMax \ 2) Step 2
           intNew = intMax - intI

           ' Swap the first bytes.
           bytTemp = abytIn(intI)
           abytIn(intI) = abytIn(intNew - 1)
           abytIn(intNew - 1) = bytTemp

           ' Swap the second bytes.
           bytTemp = abytIn(intI + 1)
           abytIn(intI + 1) = abytIn(intNew)
           abytIn(intNew) = bytTemp
       Next intI

       dhReverse = abytIn
   End If
End Function
И снова отступление
Виталий решил задачу, использовав мощные готовые функции из книги К.Гетца и М.Гилберта "Программирование на..." Здесь есть свои плюсы и минусы. Плюс - автор решения внимательно изучает язык, читает литерату и знает где искать решение. Действительно, при решении поставленной задачи не важно, используешь ли свои алгоритмы или готовые. Главное - решение задачи. Минус - все-таки мы решаем задачи, а не выполняем работу. Желательно самим найти решение, тем самым приобретая опыт программирования. Кстати, в предложенном варианте тоже не учитывались знаки препинания. Но автор, на мое замечание, мгновенно среагировал, заявив, что функция dhTranslate является универсальной, и необходимо лишь в качестве второго ее аргумента перечислить все символы которые вы хотите убрать

Решение-победитель

Но победителем все-таки стал автор под ником *Socr@t*(Anton8@...). Вот его решение
  Private Sub Command1_Click()
  Dim Fraza$, InvFraza$, XXVal&
  Dim Cash&, curchar&
  Cash = Len(Text1.Text) + 1
  Fraza = Text1.Text
  For XXVal = 1 To Cash
      If Cash = XXVal Then Exit For
          curchar = Asc(Mid$(Fraza, Cash - XXVal, 1))
             If curchar >= 97 And curchar <= 122 Or _
             curchar >= 65 And curchar <= 90 Or  _
             curchar >= 192 Or _
             curchar >= 48 And curchar <= 57 _
             Then InvFraza = InvFraza + Chr$(curchar) _
             Else: Fraza = Mid$(Fraza, 1, Cash - XXVal - 1) & Mid$(Fraza,
Cash - XXVal + 1)
   Next XXVal
 IF lcase(fraza)=lcase(invfraza) then msgbox "Палиндром"
  End Sub
И хотя, Сократ решил задачу со второй попытки, его решение оказалось коротким и работающим.
Мои поздравления, *Socr@t*! Ура-а-а!
Есть желающие упростить решение?

Новые задания

Итак, вопрос закрываем. Но неожиданно всплыл другой вопрос. Помните мой первый вопрос - как поменять значения двух переменных, не используя третью переменную? Я распинался перед вами, что программист должен учитывать все возможные варианты и сам угодил в свою же ловушку. Я забыл, что переменные могут быть и строковыми и здесь решение типа
a = a + b
b = a - b
a = a - b
не пройдет. Указал мне на это Виктор(vitos@...), заявив: В общем то не так уж это и важно, просто глаз резануло от такого расплывчатого задания, незнающий народ ведь будет мучаться :))
Мне казалось, что всем понятно, что речь идет о числах и народ не будет мучится :-) Но я ошибался. Кто-то стал решать эту задачу, используя строки! Некто lord(lord@...) прислал такое решение
Private Sub Command1_Click()
Dim d As String
Dim f As String
d = Text1.Text
f = Text2.Text
Text1.Text = f & " " & d
Text2.Text = d & " " & f
d = InStr(Text1.Text, Chr(32))
f = InStr(Text2.Text, Chr(32))
Text1.Text = Left(Text1.Text, d - 1)
Text2.Text = Left(Text2.Text, f - 1)
End Sub
Но решение не корректно. В данном контексте текстовые поля можно считать за переменные, способные хранить промежуточные значения. Фактически, используются четыре переменные. Но решение натолкнуло на мысль, а можно ли все-таки решить задачу? Так как мне не известно, существует ли решение, то считайте это задачей вне конкурса. Итак, существуют две переменные a="abc" b="def" На форме только одна кнопка. При нажатии, значения меняются и выводятся через Print. Удачи!

Новое задание будет предложено в следующием очередном выпуске рассылки. Не пропустите!
Александр Климов - ведущий рассылки
http://rusproject.narod.ru

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу
Рейтингуется SpyLog

В избранное