2011-gre-cs-practice-book.pdf/Q46 — различия между версиями

Материал из DISCOPAL
Перейти к: навигация, поиск
(Вопрос: Q46-08c765)
 
(не показано 12 промежуточных версий 2 участников)
Строка 22: Строка 22:
 
}
 
}
 
</code-c>
 
</code-c>
 
 
  
 
Какие из следующих утверждений могут служить инвариантом цикла для указанного выше цикла while?
 
Какие из следующих утверждений могут служить инвариантом цикла для указанного выше цикла while?
  
I. <m>i<10i<10</m> или <m>j<10j<10</m>
+
* I. i < 10 или j < 10
II. <m>i<11i<11</m> и <m>j<11j<11</m>
+
* II. i < 11 и j < 11
III. <m>k=i+jk=i+j</m>
+
* III. k = i + j
  
 
=== Ответы ===
 
=== Ответы ===
* (A) Только I   
+
* Только I   
* (B) I и II   
+
* I и II   
* (C) I и III   
+
* I и III   
* (D) II и III   
+
* II и III   
* Правильный ответ: (E) I, II и III
+
* Правильный ответ: I, II и III
  
 
=== Объяснение ===
 
=== Объяснение ===
  
{{cstest-source|2011-gre-cs-practice-book.pdf|46|46}}
+
{{cstest-source|2011-gre-cs-practice-book.pdf|37|46}}
  
 
Разберём каждое из утверждений
 
Разберём каждое из утверждений
  
'''инвариант цикла''' – это некоторое утверждение о переменных, которое остаётся истинным:
+
* I: i < 10 или j < 10  
 
+
* '''перед входом''' в цикл, 
+
* '''после каждой итерации''' цикла (если цикл продолжается), 
+
* '''при завершении''' цикла.
+
 
+
 
+
* I: <m>i < 10</m> или <m>j < 10</m>
+
 
+
*# Условие цикла: <m>i < 10 \land j < 10</m>. 
+
*# Если мы '''находимся внутри цикла''', то одновременно <m>i < 10</m> и <m>j < 10</m> (то есть и то, и другое меньше 10). 
+
*#* Из того, что <m>i < 10</m> '''и''' <m>j < 10</m>, автоматически следует более слабое утверждение <m>i < 10</m> '''или''' <m>j < 10</m>.
+
 
+
*# Значит, пока цикл ещё не прерван, утверждение «<m>i < 10</m> или <m>j < 10</m>» будет верно всегда (оно слабее, чем само условие цикла).
+
*# '''I действительно является инвариантом'''.
+
 
+
---
+
 
+
* II: <m>i < 11</m> и <m>j < 11</m>
+
 
+
*# Во время работы цикла <m>i</m> и <m>j</m> могут принимать значения от <m>0</m> до <m>9</m> включительно.
+
*#* Как только <m>i</m> станет равным <m>10</m> (или <m>j = 10</m>), цикл прервётся. 
+
*# Внутри цикла мы имеем <m>i \le 9</m> и <m>j \le 9</m>.
+
*#* Отсюда немедленно следует, что <m>i < 11</m> и <m>j < 11</m>. 
+
*# При приращении <m>i</m> или <m>j</m> на <m>1</m> они не могут «перескочить» сразу через <m>11</m>, так что в любой момент внутри цикла условие <m>i < 11</m> и <m>j < 11</m> сохраняется.
+
 
+
*# '''II тоже является инвариантом''' (он даже слабее, чем <m>i < 10 \land j < 10</m>, но тем не менее остаётся истинным всюду, пока цикл не завершён).
+
  
---
+
Из того, что i<10 и j<10, автоматически следует более слабое утверждение i<10 или j<10.
 +
Пока цикл ещё не прерван, утверждение «i<10 или j<10» будет верно всегда. Следовательно, I действительно является инвариантом.
  
* Утверждение III: <m>k = i + j</m>
+
* II: i < 11 и j < 11
  
*# Проверим на шагах цикла:
+
Внутри цикла мы имеем i <= 9 и j <= 9. Отсюда немедленно следует, что i < 11 и j < 11. Следовательно, II также является инвариантом.
*#* '''Начальные значения''': <m>i = 0</m>, <m>j = 0</m>, <m>k = 0</m>.
+
*#*# Очевидно, <m>k = i + j = 0</m>. Утверждение верно перед входом в цикл.
+
  
*#* '''Шаг цикла''':
+
* III: k = i + j
*#*# Если <m>A[i] > B[j]</m>, то выполняется:
+
<m>
+
k = k + 1, \quad i = i + 1.
+
</m> 
+
*#*# Новая сумма <m>(i + j)</m> увеличится на <m>1</m> (так как <m>i</m> увеличили на <m>1</m>, <m>j</m> не трогали). Параллельно <m>k</m> тоже увеличился на <m>1</m>. Значит, соотношение <m>k = i + j</m> сохранится.
+
  
*#*# Если <m>A[i] \le B[j]</m>, то выполняется:
+
Перед входом в цикл имеем k = i + j = 0. В то же время либо инкрементируется i, либо j. Таким образом, соотношение сохраняется при переходе между итерациями и утверждение III является инвариантом.
<m>
+
k = k + 1, \quad j = j + 1.
+
</m>
+
*#*# Аналогично, теперь <m>(i + j)</m> снова увеличилось на <m>1</m> (увеличился <m>j</m>), и <m>k</m> тоже на <m>1</m>. Значит, <m>k</m> остаётся равным <m>i + j</m>.
+
  
*# После каждой итерации связь <m>k = i + j</m> сохраняется.
+
{{question-ok|[[Участник:StasFomin|StasFomin]] 09:59, 9 января 2025 (UTC)}}
*# '''III однозначно является инвариантом'''.
+
  
{{question-ok|}}
+
[[Категория:Понимание кода]]
{{reserve-task|[[Участник:Nikitashapovalov|Nikitashapovalov]] 20:53, 8 января 2025 (UTC)}}
+

Текущая версия на 10:01, 9 января 2025

Вопрос: Q46-08c765

i = 0;
j = 0;
k = 0;
 
while (i < 10 and j < 10)
{
    if (A[i] > B[j])
    {
        C[k] = A[i];
        k = k + 1;
        i = i + 1;
    }
    else
    {
        C[k] = B[j];
        k = k + 1;
        j = j + 1;
    }
}

Какие из следующих утверждений могут служить инвариантом цикла для указанного выше цикла while?

  • I. i < 10 или j < 10
  • II. i < 11 и j < 11
  • III. k = i + j

Ответы

  • Только I
  • I и II
  • I и III
  • II и III
  • Правильный ответ: I, II и III

Объяснение

Исходники — вопрос 46 на 37 странице книги «2011-gre-cs-practice-book.pdf»

Разберём каждое из утверждений

  • I: i < 10 или j < 10

Из того, что i<10 и j<10, автоматически следует более слабое утверждение i<10 или j<10. Пока цикл ещё не прерван, утверждение «i<10 или j<10» будет верно всегда. Следовательно, I действительно является инвариантом.

  • II: i < 11 и j < 11

Внутри цикла мы имеем i <= 9 и j <= 9. Отсюда немедленно следует, что i < 11 и j < 11. Следовательно, II также является инвариантом.

  • III: k = i + j

Перед входом в цикл имеем k = i + j = 0. В то же время либо инкрементируется i, либо j. Таким образом, соотношение сохраняется при переходе между итерациями и утверждение III является инвариантом.