My Open Source Projects
O.S.S.
My Free Software
Free Soft
Articles and Documentation (in Russian)
Articles
My photoalbum and photographer notes
Photo
Windows Logos (Cool replacements for Windows 95/98 startup, shutdown and switchoff screens)
WinLogos
Site Archive (Site design gallery, dead sites gallery, old guestbooks...)
Archive
Contact information (quick email, email, ICQ etc)
Contacts
ENG
RUS

Школьные олимпиадные задачи на BASIC

6 ноября 1995г. я удосужился выиграть школьную олимпиаду Железнодорожного района (города Н-ска, естественно) по информатике. Легко. Не могу сказать, что там были интересные или сложные задания - подзадач такой и большей степени сложности по несколько штук в любой более-менее серьезной программе. На олимпиаде, конечно, дело в том, чтобы решить несколько абсолютно разных и непонятно откуда взявшихся задач за 2 часа в неидеальной для думания обстановке гонки.
К сожалению, из-за недооценки преподавателем моих возможностей мне не довелось попасть на городскую олимпиаду и показать и там, где проводят холодное время года эти самые земноводные... ну, которые еще свистят вечно - залезут повыше, и глушат всех.
Программы портировались с Yamaha MSX-2 (MSX-BASIC) на QBASIC и назад, поэтому не используют нормальных операторов управления типа LOOP и т. д.
Первые три задачи - собственно орудие победы (сейчас смотрю: ну и что в них такого?) Остальные были решены в процессе моральной подготовки.

Если вы хотите попробовать эти программы на "Ямахе", можно использовать оригинальные MSX-версии программ (они есть только для трех олимпиадных), либо портировать "перебранные" программы с QBASIC. Для портирования программ назад на MSX нужно: проставить номера строк, заменить текстовые метки на соответствующие номера; заменить SELECT CASE на ON... GOTO, "собрать" многострочные конструкции IF... THEN... ELSE... END IF в однострочные IF... THEN... ELSE... В основном, на этом различия и заканчиваются (программы перенесены с минимальной модификацией).
Кстати, есть способ запустить программы для MSX под Windows - использовать MSX Emulator (см. в разделе Ссылки).

Решение числовой головоломки

Решить головоломку (A, B, C - с клавиатуры):
          ???
         x ??
       ------
         A???
        B???
        ????C

Выдать все возможные решения.

INPUT "Enter A, B, C: ", a, b, c
m1 = a * 1000
x1 = m1 + 999
m2 = b * 1000
x2 = m2 + 999
FOR x = 111 TO 999
  FOR y1 = 1 TO 9
    s1 = y1 * x
    IF NOT (s1 < m1 OR s1 > x1 OR (s1 MOD 10 <> c)) THEN
      FOR y2 = 1 TO 9
        s2 = y2 * x
        s = s2 * 10 + s1
        IF s < 99999! AND s2 >= m2 AND s2 <= x2 THEN
          PRINT "-----"
          PRINT USING "  ###"; x
          PRINT USING "   ##"; y1 + y2 * 10
          PRINT USING " ####"; s1
          PRINT USING "#### "; s2
          PRINT USING "#####"; s
        END IF
      NEXT
    END IF
  NEXT
NEXT

Определение, является ли фраза палиндромом

Определить, является ли введенная фраза палиндромом (т. е., читающейся задом наперед точно так же, например: "Ленин ел", "А роза упала на лапу Азора", "Аргентина манит негра").

LINE INPUT "Кандидат в палиндромы? "; p$
l$ = "абвгдежзийклмнопрстуфхцчшщъыьэюя"
u$ = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
m$ = " :,.+-;*?/\|~'`!@#$^&()[]{}%=" + CHR$(34)

FOR t = 1 TO LEN(p$)
  q$ = MID$(p$, t, 1)
  ln = INSTR(l$, q$)
  IF ln > 0 THEN q$ = MID$(u$, ln, 1) ELSE IF INSTR(m$, q$) > 0 THEN q$ = ""
  a1$ = a1$ + q$: a2$ = q$ + a2$
NEXT
IF a1$ = a2$ THEN PRINT "Палиндром!" ELSE PRINT "Не палиндром."

Разложение числа на простые множители

INPUT "Число"; x
PRINT "Простые множители"; x; ":"
os = x
newdiv:
  IF os = 1 THEN PRINT : END
  IF os MOD 2 = 0 THEN os = os / 2: PRINT 2; : GOTO newdiv
  FOR k = 3 TO os / 3 STEP 2
    IF os MOD k = 0 THEN os = os / k: PRINT k; : GOTO newdiv
  NEXT
PRINT os

Решение головоломки ((((1?2)?3)?4)?5)?6=36

Заменить "?" на знаки арифметических операций так, чтобы получилось верное равенство.
Не самое красивое решение - с использованием функций было бы гораздо лучше... Но в MSX-BASIC возможности определения функций крайне ограничены. Отличие QBASIC-версии от оригинала в использовании SELECT CASE вместо ON...GOTO.

' ((((1?2)?3)?4)?5)?6=36
DIM s(5), t$(4)
t$(1) = "+": t$(2) = "-": t$(3) = "/": t$(4) = "*"
FOR s1 = 1 TO 4: s(1) = s1
FOR s2 = 1 TO 4: s(2) = s2
FOR s3 = 1 TO 4: s(3) = s3
FOR s4 = 1 TO 4: s(4) = s4
FOR s5 = 1 TO 4: s(5) = s5
  a = 1
  FOR i = 1 TO 5
    j = i + 1
    SELECT CASE s(i)
      CASE 1: a = a + j
      CASE 2: a = a - j
      CASE 3: a = a / j
      CASE 4: a = a * j
    END SELECT
  NEXT
  IF a = 36 THEN
    PRINT "36=((((1"; t$(s1); "2)"; t$(s2); "3)"; 
    PRINT t$(s3); "4)"; t$(s4); "5)"; t$(s5); "6"
  END IF
NEXT s5, s4, s3, s2, s1

Суммирование натуральных чисел произвольной длины

INPUT "Введите складываемые числа (a, b)"; s1$, s2$
IF LEN(s1$) < LEN(s2$) THEN SWAP s1$, s2$
s2$ = STRING$(LEN(s1$) - LEN(s2$), "0") + s2$
PRINT : PRINT : PRINT "  "; s1$: PRINT "+ "; s2$
FOR i = LEN(s1$) TO 1 STEP -1
  ri = ASC(MID$(s1$, i, 1)) + ASC(MID$(s2$, i, 1)) - ASC("0") * 2 + pe
  pe = ri \ 10
  ri = ri MOD 10
  r$ = MID$(STR$(ri), 2, 1) + r$
NEXT
PRINT "=";
IF pe > 0 THEN r$ = MID$(STR$(pe), 2, 1) + r$ ELSE PRINT " ";
PRINT r$

Нахождение многочлена по его корням

INPUT "Число корней? ", n
DIM a(n), x(n), t(n)
FOR i = 0 TO n - 1
  PRINT "x("; i; ")";
  INPUT x(i)
NEXT
a(0) = 1
FOR st = 0 TO n - 1
  t(0) = 0
  FOR i = 0 TO st: t(i + 1) = a(i): NEXT
  FOR i = 0 TO st: t(i) = t(i) - a(i) * x(st): NEXT
  FOR i = 0 TO st + 1: a(i) = t(i): NEXT
NEXT

PRINT "Уравнение:"
FOR i = n TO 1 STEP -1
   IF a(i) > 0 THEN
     PRINT "+("; a(i); "* X ^"; i; ")";
   ELSE
     IF a(i) < 0 THEN PRINT "-("; -a(i); "* X ^"; i; ")";
   END IF
NEXT
IF a(0) <> 0 THEN PRINT "+("; a(0); ")";
PRINT "=0"

Перестановки

Выдает таблицу всех возможных перестановок n элементов.

INPUT "Число элементов? ", n
DIM a(n), in(n), p(n): i = 1
FOR w = 1 TO n: a(w) = w: NEXT

NEWFOR:  in(i) = 1
CHKFOR:  IF in(i) > n THEN IF i = 1 THEN END ELSE i = i - 1: RETURN
           IF p(in(i)) = 1 THEN GOTO NEXTFOR
             IF i = n THEN GOSUB SHOW: i = i - 1: RETURN
             p(in(i)) = 1
             i = i + 1: GOSUB NEWFOR
             p(in(i)) = 0
NEXTFOR: in(i) = in(i) + 1: GOTO CHKFOR

SHOW:
    FOR w = 1 TO n: PRINT USING "####"; a(in(w)); : NEXT
    x$ = INPUT$(1)
    PRINT
RETURN

Разложение на слагаемые

Выдает все возможные разложения целого числа на слагаемые. Со слишком большими числами какие-то проблемы - резко падает быстродействие (?)

INPUT "Раскладываемое число? ", n
DIM s(n), m(n): m(1) = n: i = 1

NEWFOR:  s(i) = 1
CHKFOR:  IF s(i) = m(i) THEN
           GOSUB SHOW
           IF i = 1 THEN END ELSE i = i - 1: RETURN
         END IF
             m(i + 1) = m(i) - s(i)
             i = i + 1: GOSUB NEWFOR
         s(i) = s(i) + 1: GOTO CHKFOR

SHOW:
    FOR w = 1 TO i - 1
      IF s(w + 1) > s(w) THEN RETURN
    NEXT
    PRINT n; "="; s(1);
    FOR w = 2 TO i: PRINT "+"; s(w); : NEXT: PRINT
RETURN
Go to Start page
© Sergey A. Galin, 1998-2009http://sageshome.net/downloads/solutions...>>
Time: 0.022s · Total: 1060238/1253299