Школьные олимпиадные задачи на 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-2024http://sageshome.net/downloads/solutions...>>
Time: 0.012s · Total: 2672320/2952264