# Regional Stage 2025–2026, Tour 2: Full Paper

*English translation by SOTA – AI Community of the Russian original. Organisers who would like this translation removed can email sota.ai.community@gmail.com.*

All-Russian School Olympiad in Informatics 2025–2026, Regional Stage, Grades 9–11<br>
“Artificial Intelligence” profile, Tour 2, 19 January 2026

---

## A. Recommendation Islands

**Points for the task:** 100, 20 for each question<br>
**Answer submission format:** entering the answer or uploading a file, depending on the question<br>
**Number of attempts:** 10 for each subtask<br>
**Submission that counts:** the last one

### Statement

You work as an analyst in the team of an online marketplace. On the website, each product has a card with information (category, price, rating, brand, availability) and a “Customers also viewed” block, which shows other products that users often go to from this card.

You have been given an export of two tables in CSV format:

- `items.csv` — a list of products and their properties.
- `also_viewed.csv` — a list of “customers also viewed” transitions.

You need to answer several questions about the products and the structure of the recommendation graph. The answers must be obtained by processing the data programmatically (for example, in Python using pandas and simple graph algorithms).

The file `items.csv` contains information about the products. Each row is one product. Fields:

- `item_id` – a unique integer identifier of the product.
- `category` – the product category (phones, accessories, laptops, books, home, toys).
- `price` – the price of the product in conventional units (an integer).
- `rating` – the rating of the product according to reviews (a real number from 3.0 to 5.0 in steps of 0.1).
- `brand` – the brand name (a string).
- `in_stock` – 1 if the product is in stock, 0 if it is not.

The file `also_viewed.csv` describes the links between products in the “customers also viewed” block. Each row specifies a pair of products (`item_from`, `item_to`) for which it has been recorded that users often go from one to the other. In the tasks that refer to the “neighbours” of a product or to transitions between products, we assume that such a link works in both directions: if the table contains a row with the pair of products $A$ and $B$ (in any order), then $A$ and $B$ are considered directly linked recommendations. The “neighbours” of a product $X$ are all the products that are paired with $X$ in at least one row, regardless of whether $X$ is given in `item_from` or in `item_to`.

### Scoring

You can get up to 100 points for this task. Each item is worth 20 points.

Test results for subtasks 1, 2, 3 and 5 are **not available** during the tour. In all subtasks, the last submission counts.

---

### A1 – Question 1

How many products in the category phones have a rating of at least 4.5 (rating $\ge 4.5$) and are also in stock (`in_stock` $= 1$)?

#### Output format

One integer – the number of such products.

#### Answer evaluation metric

Exact match of the entered answer.

---

### A2 – Question 2

Consider only the products in the category laptops. For each brand, compute the average price of that brand's laptops. Which brand has the highest average price among the laptops?

If several brands have the same highest average price, you may output any of them.

#### Output format

One word – the brand name (the brand string from the file `items.csv`).

#### Answer evaluation metric

Exact match of the entered answer.

---

### A3 – Question 3

The marketing team wants to divide the products into three segments by price and rating:

- segment **premium** – if rating $\ge 4.5$ and price $\ge 50000$;
- segment **standard** – if rating $\ge 4.0$ and price $< 50000$;
- segment **budget** – in all other cases.

For each product, determine its segment (**premium** / **standard** / **budget**) according to these rules. Among the products that are in stock (`in_stock` $= 1$), count how many products belong to the segment **premium**.

#### Output format

One integer — the number of products in the segment premium among the products with `in_stock` $= 1$.

#### Answer evaluation metric

Exact match of the entered answer.

---

### A4 – Question 4

Consider the file `also_viewed.csv`. Find all the products that appear at least once in the field item_to (that is, the products that were shown at least once in the “Customers also viewed” block). For each category, count how many distinct products of that category appear in `item_to` at least once.

You need to prepare a table with two columns:

- `category` – the name of the category;
- `cnt` – the number of distinct products of this category that appear in `item_to`.

The table should include all the categories that are present in the file `items.csv`, even if `cnt` $= 0$ for some category. The rows of the table must be sorted by category name in alphabetical order.

#### Output format

A text file `answer4.csv` in CSV format with a header and two columns:

`category,cnt`

The file must contain exactly one row for each category.

#### Answer evaluation metric

The fraction of the categories `category` in your answer file for which the count `cnt` matches the count `cnt` in the reference answer file.

---

### A5 – Question 5

We consider the links between products as described in the section “Dataset description”: two products are considered directly linked if `also_viewed.csv` contains a row in which they appear as a pair (in any order).

Let us call a “recommendation island” any set of products within which one can get from any card to any other card by following direct links between products (via neighbours). If two products belong to different recommendation islands, then no chain of such transitions leads from one of them to the other.

We are interested in the recommendation islands that contain both at least one product of the category phones and at least one product of the category accessories.

How many such recommendation islands are there in our data?

#### Output format

One integer – the number of “recommendation islands” that contain both at least one phones product and at least one accessories product.

#### Answer evaluation metric

Exact match of the entered answer.

---

## B. Clustering

**Points for the task:** 100<br>
**Answer submission format:** uploading an answer file in .csv format<br>
**Number of attempts:** 20<br>
**Submission that counts:** the last one

### Statement

On his way to the regional stage of the All-Russian School Olympiad in AI, Misha found a USB flash drive on a key ring with the words “methodological commission” written on it. The flash drive turned out to contain a table file named `data.csv`. Since Misha found no target variable in the csv file, he rightly concluded that this must be a clustering task. However, Misha could not find any information about the number of clusters anywhere. Help Misha work out the number of clusters and cluster the data correctly.

### Input format

The following files are attached to the task:

- `data.csv` - contains the object–feature matrix (each row of the table is an object, each column is a feature). The column `id` is the object identifier. The other columns are features.
- `baseline.ipynb` - a notebook with a baseline solution to the task.
- `submission.csv` - an example of the solution that you need to submit to the testing system.

### Output format

You need to submit, as your submission, the file `submission.csv` containing two columns:

- `id` - the identifier of the object from `data.csv`.
- `cluster` - the cluster you predicted for the object (a positive integer).

### Scoring

You can get up to 100 points for this task.

The data are split into a public and a private part. When you submit submission.csv, you are shown the result on the public part. After the contest ends, your result will be recalculated on the private part.

After the end of the stage, your metric will be converted to a 100-point scale according to the following rule:

- the result of the **baseline solution** (ARI=0.0) is worth **0 points**;
- the result of the **author's solution** (ARI=0.9814) is worth **100 points**;
- results between these two points are distributed linearly.

### Answer evaluation metric

This task uses the metric **ARI (Adjusted Rand Index)**. The more pairs of objects Misha assigns to clusters correctly (for example, if the two objects are in different clusters and Misha also puts them in different clusters, OR the two objects are in the same cluster and Misha also puts them in the same cluster), the higher this metric. $ARI$ takes the value 0 for a random partition into clusters and the value 1 for a perfectly correct partition, and it can take negative values for a poor partition that is worse than random.

Example of computing the **ARI** metric in *Python*:

```python
from sklearn.metrics import adjusted_rand_score

labels_true = [0, 0, 1, 1, 2, 2]
labels_pred = [1, 1, 0, 0, 2, 2]

ari = adjusted_rand_score(labels_true, labels_pred)
print("ARI =", ari)
```

---

## C. Apartment Rental Prices

**Points for the task:** 100<br>
**Answer submission format:** uploading an answer file in .csv format<br>
**Number of attempts:** 20<br>
**Submission that counts:** the last one

### Statement

While Semyon was preparing to solve the regional stage of the All-Russian School Olympiad and dreaming of how he would earn his BVI (university admission without entrance examinations), he decided to estimate what kind of apartment he could rent with the money he had saved from ML olympiads if he were not given a place in the dormitory next to the university. To do this, he scraped data from property rental websites and decided to build a model that predicts the rental price, so that he could then find the best deals. However, because the data were collected rather carelessly and from different websites, the dataset turned out to be quite “dirty”. Help Semyon process the data carefully and obtain the best possible quality of rental price prediction.

### Input format

The following files are attached to the task:

- `train.csv` - the column `price` is the target variable. The other columns are features.
- `test.csv` - the column `id` is the object identifier. The other columns are features.
- `baseline.ipynb` - a notebook with a baseline solution to the task.
- `submission.csv` - an example of the solution that you need to submit to the testing system.

### Output format

You need to submit, as your submission, the file `submission.csv` containing two columns:

- `id` - the identifier of the object from `test.csv`.
- `price` - the target variable you predicted.

### Scoring

You can get up to 100 points for this task.

The data are split into a public and a private part. When you submit `submission.csv`, you are shown the result on the public part. After the contest ends, your result will be recalculated on the private part.

After the end of the stage, your metric will be converted to a 100-point scale according to the following rule:

- the result of the **baseline solution** (RMSE=21.046) is worth **0 points**;
- the result of the **author's solution** (RMSE=13.8) is worth **100 points**;
- results between these two points are distributed linearly.

### Answer evaluation metric

This task uses the metric **RMSE**.

Strict mathematical definition of the metric **RMSE**:

$$
\mathrm{RMSE} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2}
$$

$y_i$ — the true value, $\hat{y}_i$ — the prediction, $n$ — the number of objects.

Example of computing the **RMSE** metric in *Python*:

```python
from sklearn.metrics import root_mean_squared_error

y_true = [3.0, -0.5, 2.0, 7.0]
y_pred = [2.5,  0.0, 2.1, 7.8]

rmse = root_mean_squared_error(y_true, y_pred)
print("RMSE =", rmse)
```

---

## D. The Martian Archivist

**Points for the task:** 100<br>
**Answer submission format:** uploading an answer file in .csv format<br>
**Number of attempts:** 20<br>
**Submission that counts:** the last one

### Statement

During the third year of the expedition to Valles Marineris on Mars, our acquaintance Andrey, an engineer and a specialist in extraterrestrial systems, came across something incredible: a perfectly preserved crystalline memory module hidden deep beneath the surface of the canyon.

When the module was carefully extracted and connected to power, it awakened an ancient Martian AI that called itself “Archivist Unit F”, the keeper of the knowledge of a vanished civilisation. The Archivist revealed that its memory holds extensive information about the crystals that the ancient Martians used in their laboratories and energy reactors.

Each crystal was described by an embedding: a vector of length 16 reflecting its structure, composition, resonance properties and many other characteristics that humans cannot yet interpret directly. Besides the embedding, the Archivist also stored the class (one of 25 possible), that is, the type or functional purpose of the crystal.

But over thousands of years under the Martian dust, the Archivist had been damaged.

For many crystals, the class information was lost completely.

For others, it was preserved only partially: instead of one exact class, the Archivist gave several possible options, sometimes reasonable and sometimes completely random. It seems that the data structures inside the module got mixed up, and no simple method of recovering the information works.

Andrey and his team are extremely interested in the ancient knowledge about Martian crystals: understanding their properties could lead to a breakthrough in energy-intensive technologies and materials science.

That is why they are turning to you.

Your task is to help the Archivist restore the true classes of those crystals whose information was lost or damaged. You will be given:

- the embeddings of the crystals,
- the correct classes for some of them,
- ambiguous lists of possible classes for the others,
- and also a set of crystals whose classes you have to predict.

Like the ancient AI, you will have to work under uncertainty and with incomplete information. However, modern machine learning methods offer a chance to recover a significant part of the lost knowledge, if they are applied carefully and inventively enough.

### Input format

The following files are attached to the task:

- `train.csv` - contains information about the crystals for which the true or possible labels are known. Fields:
  - `id` — the unique identifier of the object.
  - `F{i}`, where $i \in \{1, \dots, 16\}$ — the components of the embedding.
  - `labels` — the set of possible classes for this object (the true class may be among them, but it may also be absent).
- `test.csv` — a file with the embeddings of the crystals whose classes must be predicted. It is guaranteed that each object belongs to exactly one of the 25 classes.
- `baseline.ipynb` — a notebook with a baseline solution to the task.
- `submission.csv` — an example of the solution that you need to submit to the testing system.

### Output format

You need to submit, as your submission, the file `submission.csv` containing two columns:

- `id` — the identifier of the object from test.csv.
- `class` — the class label predicted by the model

### Scoring

The maximum for the task is 100 points.

The test data are divided into a public and a private part.

After you submit a solution, the system shows the result on the public part.

The final result will be calculated on the private part after the contest ends. After the end of the stage, your metric will be converted to a 100-point scale according to the following rule:

- the result of the **baseline solution** (Accuracy=0.2717) is worth **0 points**;
- the result of the **author's solution** (Accuracy=0.8) is worth **100 points**;
- results between these two points are distributed linearly.

### Answer evaluation metric

This task uses the metric **Accuracy**. It is calculated as the fraction of objects in the test set whose class is predicted correctly.

Strict mathematical definition of the metric **Accuracy**:

$$
\text{Accuracy} = \frac{\text{number of correct answers}}{\text{total number of test crystals}}.
$$

Example of computing the **Accuracy** metric in *Python*:

```python
from sklearn.metrics import accuracy_score

y_true = [0, 1, 2, 2, 1]
y_pred = [0, 2, 1, 2, 1]

acc = accuracy_score(y_true, y_pred)
print("Accuracy =", acc)
```
