Читаем Программирование игр и головоломок полностью

Тогда мы можем начать с p = 0 и q = n + 1. Напишите соответствующую программу, вовсе не заботясь заранее о значениях a[0] и a[n + 1] и оставляя в неопределенном положении задачу эффективного описания таблицы (некоторые языки, такие как Фортран или LSE, не допускают индекса ноль — один только бог знает почему…). Покажите, что единственный индекс, для которого фактически приходится читать значение элемента таблицы, — это индекс r. Так как r всегда строго содержится в интервале (p, q), причем p не убывает, a q не возрастает, то r всегда строго больше 0 и не меньше n. Таким образом, элементы 0 и n + 1 никогда не опрашиваются. Поэтому и нет необходимости их материализовывать. Объявите массив (таблицу) с индексом, пробегающим от 1 до n, и все пройдет без сучка и задоринки…

Головоломка 30.

Это — задача, на которой я заваливаю профессионалов. Совершенно очевидно, что обе цепочки символов играют одну и ту же роль. Следовательно, в программе есть симметрия, которая касается способа обращения с этими цепочками. Вот — более или менее символически — программа, которую пишут профессионалы:

100 i = 0; j := 0.

110 продвинуть i к ближайшему символу в цепочке a, не являющемуся пробелом

120 ЕСЛИ мы вышли из a ТО ПЕРЕЙТИ К 200 КОНЕЦ_ЕСЛИ

130 продвинуть j к ближайшему символу в цепочке b, не являющемуся пробелом

140 ЕСЛИ мы вышли из b ТО ПЕРЕЙТИ К 300 КОНЕЦ_ЕСЛИ

150 ЕСЛИ a[i] = b[j] ТО ПЕРЕЙТИ К 110

160 ПЕРЕЙТИ К 800

200 продвинуть j к ближайшему символу в цепочке b, не являющемуся пробелом

210 ЕСЛИ мы вышли из b ТО ПЕРЕЙТИ К 900 КОНЕЦ_ЕСЛИ

220 ПЕРЕЙТИ К 800

300 продвинуть i к ближайшему символу в цепочке а, не являющемуся пробелом

310 ЕСЛИ мы вышли из a ТО ПЕРЕЙТИ К 900 КОНЕЦ_ЕСЛИ

800 результат := ЛОЖЬ; ПЕРЕЙТИ К 1000

900 результат := ИСТИНА

Эта программа понятна. В 150 находим два символа, не являющихся пробелами. Если они совпадают, то нужно продолжать маршрут, а если они различны, то и цепочки различны (строчка 800).

Если в 120 констатируется, что все символы цепочки а уже испытаны, причем каких-либо различий с уже изученными символами цепочки b но обнаружено, то имеется выбор одной из двух возможностей (строки 200 и 210):

— либо в цепочке b нет ни одного символа, не являющегося пробелом (что приводит к тому, что в поисках такого символа мы выходим из b), и цепочки совпадают (строчка 900), либо мы обнаруживаем в цепочке b символ, не являющийся пробелом; эта цепочка включает символы, не входящие в a, и, следовательно, результат есть ЛОЖЬ (строка 800).

То же самое происходит, когда исчерпывается цепочка b (из строчки 140 переход осуществляется к строчке 300).

Я попытаюсь сделать из этого головоломку. Еще не слишком поздно. Найдите ошибку и исправьте ее. Но вы можете составить намного лучшую программу.

Головоломка 31.

Вот несколько идей. Вы можете сначала «отсортировать» обе цепочки, переставляя символы в каждой из них, чтобы они оказались, например, в алфавитном порядке. Когда это сделано, то цепочки должны оказаться одинаковыми, Это очень тяжеловесно…

Вы можете взять первый символ первой цепочки и посмотреть, есть ли он во второй цепочке. Если ответ отрицателен, то цепочки не являются анаграммами друг друга. Если же ответ — «да», то изымите этот символ из второй цепочки и переходите ко второму символу в цепочке a. Это ведет, по вашему выбору, к рекурсивной или к итеративной процедуре, Внимание: если вы смогли полностью пробежать a и не нашли ни одного символа, не попавшего в b, проверьте, не осталось ли чего-нибудь в b

Вы можете задать таблицу, имеющую столько же полей, сколько может быть различных символов в рассматриваемых цепочках. Если мы имеем дело с текстами и если пробелы считаются, то нужны 33 буквы и пустое место… Вы пробегаете первую цепочку и добавляете 1 в клетке, связанной с каждым встречаемым характером (вы считаете число случаев появления каждого знака), Затем вы пробегаете вторую цепочку и все пересчитываете (вычитая, а не складывая). Если в конце вы получаете таблицу, содержащую что-то кроме нулей, то цепочки не являются анаграммами.

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

Головоломка 32.

Перейти на страницу:

Похожие книги

Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Эта книга представляет собой перевод третьего издания американского бестселлера Effective C++ и является руководством по грамотному использованию языка C++. Она поможет сделать ваши программы более понятными, простыми в сопровождении и эффективными. Помимо материала, описывающего общую стратегию проектирования, книга включает в себя главы по программированию с применением шаблонов и по управлению ресурсами, а также множество советов, которые позволят усовершенствовать ваши программы и сделать работу более интересной и творческой. Книга также включает новый материал по принципам обработки исключений, паттернам проектирования и библиотечным средствам.Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Скотт Майерс , Скотт Мейерс

Программирование, программы, базы данных / Программирование / Книги по IT