AP · thinka 原创模拟试题

2024 AP AP Computer Science A 模拟试题及答案详解

Thinka May 2024 AP-Style Mock — AP Computer Science A

36 90 分钟2024
An original Thinka practice paper modelled on the structure and difficulty of the May 2024 AP AP Computer Science A paper. Not affiliated with or reproduced from AP.

部分 II: Free Response

Answer all four questions. Program segments must be written in Java. Assume all Java Quick Reference classes are available.
4 题目 · 36
题目 1 · free-response
9
This question involves a simulation of power consumption at an electric vehicle charging hub. The `ChargingHub` class maintains the current amount of stored electrical energy in kilowatt-hours (kWh) and simulates energy consumption during vehicle charging sessions.

```java
public class ChargingHub {
/**
* The amount of energy, in kilowatt-hours (kWh), currently available at the hub;
* initialized in the constructor and always greater than or equal to 0.
*/
private int availableEnergy;

/**
* Simulates one charging session with numVehicles vehicles charging or an emergency shutdown,
* as described in part (a).
* Precondition: numVehicles > 0
/
public void simulateOneSession(int numVehicles) {
/
to be implemented in part (a) */
}

/**
* Returns the number of sessions in which vehicles were able to draw energy from the hub,
* as described in part (b).
* Preconditions: numVehicles > 0, maxSessions > 0
/
public int simulateMultipleSessions(int numVehicles, int maxSessions) {
/
to be implemented in part (b) /
}

// There may be instance variables, constructors, or methods that are not shown.
}
```

(a) Write the `simulateOneSession` method, which simulates `numVehicles` vehicles charging at the hub during a single charging cycle. The method determines the total energy drawn from the hub during the session and updates the `availableEnergy` instance variable.

The simulation accounts for normal operating conditions, which occur 85% of the time, and emergency grid disconnects (abnormal conditions), which occur 15% of the time.

Under normal conditions, all vehicles successfully charge, and each vehicle draws the exact same amount of energy. The energy drawn by each vehicle is a randomly selected integer from 25 to 65 kWh, inclusive, with each integer having an equal probability of being chosen. For example, if each vehicle draws 30 kWh and 4 vehicles charge, a total of 120 kWh is demanded.
* If the total energy demanded by the vehicles is greater than `availableEnergy`, all remaining energy is consumed and `availableEnergy` becomes 0.
* Otherwise, `availableEnergy` is decreased by the total energy demanded.
* Under abnormal conditions, an emergency disconnect empties/dissipates all remaining stored energy, setting `availableEnergy` to 0.

Complete the `simulateOneSession` method below:

```java
/**
* Simulates one charging session with numVehicles vehicles charging or an emergency shutdown,
* as described in part (a).
* Precondition: numVehicles > 0
/
public void simulateOneSession(int numVehicles)
```

---

(b) Write the `simulateMultipleSessions` method. The method repeatedly calls `simulateOneSession` to simulate charging sessions for up to `maxSessions` consecutive cycles. The simulation returns the number of sessions during which vehicles were able to obtain power (that is, sessions that began with a non-zero amount of `availableEnergy`).

Consider the following examples:

Example 1: If `availableEnergy` is initially 1,500 kWh, calling `simulateMultipleSessions(8, 4)` might run 4 consecutive sessions, ending with 320 kWh of energy remaining. The method returns `4` because energy was available at the beginning of all 4 sessions.
* Example 2: If `availableEnergy` is initially 200 kWh, calling `simulateMultipleSessions(10, 5)` might deplete all energy during session 1, leaving 0 kWh. Before session 2 can run, `availableEnergy` is 0 (or reaches 0 during session 2). The method returns `2` (since energy was found on sessions 1 and 2, but no further sessions can occur).
* Example 3: If `availableEnergy` is initially 0 kWh, calling `simulateMultipleSessions(5, 10)` immediately returns `0` without running any sessions.

Assume that `simulateOneSession` works as intended, regardless of what you wrote in part (a). You must use `simulateOneSession` appropriately to receive full credit.

Complete the `simulateMultipleSessions` method below:

```java
/**
* Returns the number of sessions in which vehicles were able to draw energy from the hub,
* as described in part (b).
* Preconditions: numVehicles > 0, maxSessions > 0
*/
public int simulateMultipleSessions(int numVehicles, int maxSessions)
```
查看答案详解

解题

### Part (a) Implementation

To simulate one session:
1. Generate a pseudo-random floating-point value using `Math.random()`, which returns a value in the range \([0.0, 1.0)\).
2. Compare this value to `0.15` to represent the 15% probability of an emergency grid disconnect (abnormal condition). If triggered, set `availableEnergy = 0`.
3. Otherwise (under normal conditions with 85% probability), generate a random integer in the inclusive range \([25, 65]\). The number of possible outcomes is \(65 - 25 + 1 = 41\), so we compute `(int)(Math.random() * 41) + 25`.
4. Multiply this amount by `numVehicles` to find `totalDemand`.
5. If `totalDemand >= availableEnergy`, set `availableEnergy = 0`; otherwise, subtract `totalDemand` from `availableEnergy`.

```java
public void simulateOneSession(int numVehicles) {
if (Math.random() < 0.15) {
availableEnergy = 0;
} else {
int perVehicle = (int) (Math.random() * 41) + 25;
int totalDemand = numVehicles * perVehicle;
if (totalDemand > availableEnergy) {
availableEnergy = 0;
} else {
availableEnergy -= totalDemand;
}
}
}
```

---

### Part (b) Implementation

To simulate multiple sessions:
1. Maintain a counter for the number of sessions that successfully had power available.
2. Iterate while `count < maxSessions` and `availableEnergy > 0`.
3. In each iteration, call `simulateOneSession(numVehicles)` and increment `count` by 1.
4. Return the counter once the loop finishes.

```java
public int simulateMultipleSessions(int numVehicles, int maxSessions) {
int count = 0;
while (count < maxSessions && availableEnergy > 0) {
simulateOneSession(numVehicles);
count++;
}
return count;
}
```

评分标准

### Part (a): `simulateOneSession` (4 points)
- Point 1: Generates a random value using `Math.random()` (or equivalent random generator).
- Point 2: Correctly creates a conditional branch implementing a 15% vs 85% probability.
- Point 3: Generates a uniformly distributed random integer in the range `[25, 65]` (e.g., `(int)(Math.random() * 41) + 25`).
- Point 4 (Algorithm): Scales the per-vehicle consumption by `numVehicles`, updates `availableEnergy` appropriately, and ensures `availableEnergy` does not become negative.

### Part (b): `simulateMultipleSessions` (5 points)
- Point 5: Calls `simulateOneSession` with the argument `numVehicles`.
- Point 6: Employs a loop that executes at most `maxSessions` times.
- Point 7: Checks that `availableEnergy > 0` before executing each session (or exits when `availableEnergy == 0`).
- Point 8 (Algorithm): Accurately tracks and counts only the sessions started with available energy.
- Point 9: Returns an `int` representing the total count of completed sessions across all execution paths.
题目 2 · Free Response
9
This question involves designing a loyalty account system for a coffee shop. The `LoyaltyAccount` class keeps track of a customer's loyalty points, reward vouchers earned, and the account summary.

The `LoyaltyAccount` class contains a constructor and three methods:

* The constructor has two parameters. The first parameter is a `String` containing the name of the member, and the second parameter is a positive `int` indicating the number of points needed to earn one voucher. When a new account is created, the member has `0` points and `0` vouchers.
* The `addPoints` method has a single integer parameter representing the number of points earned on a transaction. The method adds the points to the account and automatically converts each full set of required points into a voucher (e.g., if $100$ points are required per voucher, having $230$ points total will result in $2$ vouchers earned and $30$ points remaining in the account). The `addPoints` method does not return a value.
* The `redeemVoucher` method has no parameters. If the member has at least one voucher, it decreases the voucher count by `1` and returns `true`. Otherwise, it makes no changes and returns `false`.
* The `getSummary` method has no parameters. The method returns a `String` containing the member's name, voucher count, and current points in the following format:
`"[memberName]: vouchers=[voucherCount], points=[currentPoints]"`

The following table contains a sample code execution sequence and the corresponding results.

| Statement | Value Returned
(blank if none) | Explanation |
|---|---|---|
| `LoyaltyAccount acct = new LoyaltyAccount("Alex", 100);` | | `acct` is a new `LoyaltyAccount` for `"Alex"`, requiring $100$ points per voucher. |
| `acct.getSummary();` | `"Alex: vouchers=0, points=0"` | Initial account state. |
| `acct.addPoints(60);` | | Adds $60$ points. Total points = $60$, vouchers = $0$. |
| `acct.getSummary();` | `"Alex: vouchers=0, points=60"` | |
| `acct.addPoints(70);` | | $60 + 70 = 130$ points. Earns $1$ voucher, leaving $30$ points. |
| `acct.getSummary();` | `"Alex: vouchers=1, points=30"` | |
| `acct.redeemVoucher();` | `true` | Redeems $1$ voucher, leaving $0$ vouchers. |
| `acct.redeemVoucher();` | `false` | No vouchers available to redeem. |
| `acct.addPoints(250);` | | $30 + 250 = 280$ points. Earns $2$ vouchers, leaving $80$ points. |
| `acct.getSummary();` | `"Alex: vouchers=2, points=80"` | |
| `LoyaltyAccount acct2 = new LoyaltyAccount("Taylor", 50);` | | `acct2` is an independent `LoyaltyAccount` for `"Taylor"`. |
| `acct2.getSummary();` | `"Taylor: vouchers=0, points=0"` | |

Write the complete `LoyaltyAccount` class. Your implementation must meet all specifications and conform to the examples shown in the table.
查看答案详解

解题

### Method and Class Implementation

```java
public class LoyaltyAccount
{
private String memberName;
private int pointsPerVoucher;
private int currentPoints;
private int vouchers;

public LoyaltyAccount(String name, int pointsNeeded)
{
memberName = name;
pointsPerVoucher = pointsNeeded;
currentPoints = 0;
vouchers = 0;
}

public void addPoints(int earned)
{
currentPoints += earned;
int newVouchers = currentPoints / pointsPerVoucher;
vouchers += newVouchers;
currentPoints %= pointsPerVoucher;
}

public boolean redeemVoucher()
{
if (vouchers > 0)
{
vouchers--;
return true;
}
else
{
return false;
}
}

public String getSummary()
{
return memberName + ": vouchers=" + vouchers + ", points=" + currentPoints;
}
}
```

### Explanation
1. Instance Variables: `memberName` (`String`), `pointsPerVoucher` (`int`), `currentPoints` (`int`), and `vouchers` (`int`) are declared `private` to encapsulate the state of each account object.
2. Constructor: Initializes the instance variables. `memberName` and `pointsPerVoucher` are assigned from the parameters, while `currentPoints` and `vouchers` start at `0`.
3. `addPoints(int earned)`: Adds `earned` to `currentPoints`. It computes how many full sets of `pointsPerVoucher` have been accumulated (`currentPoints / pointsPerVoucher`), adds that count to `vouchers`, and sets `currentPoints` to the remainder (`currentPoints % pointsPerVoucher`).
4. `redeemVoucher()`: Checks if `vouchers > 0`. If so, decrements `vouchers` and returns `true`; otherwise, returns `false` without modifying `vouchers`.
5. `getSummary()`: Concatenates and returns the required formatted string using string literals and instance variables.

评分标准

Scoring Criteria (9 points total):

1. Class Header (1 pt): Declares `public class LoyaltyAccount`.
* Do not award point if declared as something other than `public`.
2. Instance Variables (1 pt): Declares appropriate `private` instance variables including at least one `String` and at least one `int`.
* Do not award point if any instance variable is declared `static` or outside the class.
3. Constructor (1 pt): Declares constructor `public LoyaltyAccount(String ..., int ...)` and initializes all instance variables correctly using parameters and initial default values (`0`).
* Do not award point if constructor is declared with a return type or modifier other than `public`.
4. Method Headers (1 pt): Declares headers for all three methods: `public void addPoints(int ...)`, `public boolean redeemVoucher()`, and `public String getSummary()`.
* Do not award point if method names/types are incorrect or `public` is omitted.
5. Adding Points (1 pt): Increases the accumulated points by the parameter value in `addPoints`.
6. Voucher Conversion (1 pt): Correctly updates both the number of vouchers earned and the remaining points balance in `addPoints` using integer arithmetic / division / modulo or an equivalent loop.
7. Redemption Check (1 pt): Evaluates whether at least one voucher is available in `redeemVoucher` and returns the appropriate boolean value (`true` if available, `false` otherwise) in all cases.
8. Voucher Decrement (1 pt): Decreases `vouchers` by `1` if and only if a voucher is successfully redeemed.
9. Summary String (1 pt): `getSummary` constructs and returns the specified formatted string containing member name, voucher count, points, and required delimiters (`": vouchers="`, `", points="`).
题目 3 · free_response
9
This question involves the manipulation and analysis of a sequence of words. The following TokenList class contains an ArrayList<String> and methods used to analyze and transform strings in the list. You will write two methods of the TokenList class.

public class TokenList
{
/** Initialized in the constructor; contains no null or empty elements */
private ArrayList<String> tokens;

/**
* Returns true if each element of tokens (except the first) begins with the
* last character of the previous element, and returns false otherwise,
* as described in part (a).
* Precondition: tokens contains at least two elements.
* Postcondition: tokens is unchanged.
/
public boolean isEndMatch()
{ /
to be implemented in part (a) */ }

/**
* Returns an ArrayList<String> based on strings from tokens that end
* with suffix, as described in part (b). Each element of the returned
* ArrayList has had the trailing suffix removed.
* Postconditions: tokens is unchanged.
* Items appear in the returned list in the same order as they appear in tokens.
/
public ArrayList<String> removeMatchingTokens(String suffix)
{ /
to be implemented in part (b) */ }

// There may be instance variables, constructors, or methods that are not shown.
}



Part (a)


Write the isEndMatch method, which determines whether each element of tokens (except the first) begins with the last character of the preceding element in the list.



The following table shows two sample calls to isEndMatch.





tokens
isEndMatch Return Value
Explanation


["apple", "elephant", "tiger", "rabbit"]
true
"elephant" starts with 'e' ("apple" ends with 'e'), "tiger" starts with 't' ("elephant" ends with 't'), and "rabbit" starts with 'r' ("tiger" ends with 'r').


["dog", "goose", "eagle", "hawk"]
false
"hawk" does not start with 'e' ("eagle" ends with 'e').



Complete the isEndMatch method.


/**
* Returns true if each element of tokens (except the first) begins with the
* last character of the previous element, and returns false otherwise,
* as described in part (a).
* Precondition: tokens contains at least two elements.
* Postcondition: tokens is unchanged.
*/
public boolean isEndMatch()



Part (b)


Write the removeMatchingTokens method, which creates and returns an ArrayList<String>. The method identifies elements in tokens that end with suffix and returns a new ArrayList containing each identified string with the ending occurrence of suffix removed. Elements must appear in the returned list in the same relative order as they appear in tokens.



Consider an example where tokens contains the following strings:


["playing", "jump", "singing", "ring", "wing"]



The following table shows the ArrayList returned by some calls to removeMatchingTokens. In all cases, tokens is unchanged.





Method Call
ArrayList Returned
Explanation


removeMatchingTokens("ing")
["play", "sing", "r", "w"]
"playing", "singing", "ring", and "wing" end with "ing". The suffix is removed from each.


removeMatchingTokens("jump")
[""]
Only "jump" ends with "jump". Removing the suffix leaves an empty string "".


removeMatchingTokens("ed")
[]
None of the words in tokens end with "ed".



Complete the removeMatchingTokens method.


/**
* Returns an ArrayList<String> based on strings from tokens that end
* with suffix, as described in part (b). Each element of the returned
* ArrayList has had the trailing suffix removed.
* Postconditions: tokens is unchanged.
* Items appear in the returned list in the same order as they appear in tokens.
*/
public ArrayList<String> removeMatchingTokens(String suffix)
查看答案详解

解题

Canonical Solution



Part (a)


public boolean isEndMatch()
{
for (int i = 1; i < tokens.size(); i++)
{
String prev = tokens.get(i - 1);
String curr = tokens.get(i);

String lastCharOfPrev = prev.substring(prev.length() - 1);
String firstCharOfCurr = curr.substring(0, 1);

if (!firstCharOfCurr.equals(lastCharOfPrev))
{
return false;
}
}
return true;
}

Part (b)


public ArrayList<String> removeMatchingTokens(String suffix)
{
ArrayList<String> result = new ArrayList<String>();
for (String s : tokens)
{
if (s.length() >= suffix.length())
{
int startIndex = s.length() - suffix.length();
if (s.substring(startIndex).equals(suffix))
{
result.add(s.substring(0, startIndex));
}
}
}
return result;
}

评分标准

Part (a): isEndMatch (3 points)



  • 1 point: Accesses all adjacent pairs of tokens elements (no bounds errors).

  • 1 point: Extracts and compares the first character of the current element and the last character of the previous element.

  • 1 point: Returns true if and only if all adjacent pairs satisfy the condition, and false otherwise (algorithm).



Part (b): removeMatchingTokens (6 points)



  • 1 point: Declares and instantiates a new ArrayList<String>.

  • 1 point: Accesses all elements of tokens (no bounds errors).

  • 1 point: Correctly identifies strings in tokens that end with suffix (e.g., via substring with length check, or endsWith).

  • 1 point: Extracts a substring representing the current string with suffix removed from the end.

  • 1 point: Adds the modified string to the newly constructed ArrayList.

  • 1 point: Returns the list containing all and only identified and modified strings in the correct relative order without modifying tokens (algorithm).

题目 4 · free-response
9
This question involves analyzing a two-dimensional (2D) array representing a terrain elevation map. The TerrainMap class stores elevations as non-negative integers in a 2D array and provides methods to analyze features of the landscape.

public class TerrainMap {
/** A 2D array of integer elevations. */
private int[][] map;

/**
* Returns true if the cell at row r and column c is a local peak;
* false otherwise, as described in part (a).
* Preconditions: r is a valid row index in map.
* c is a valid column index in map.
/
public boolean isPeak(int r, int c) {
/
to be implemented in part (a) */
}

/**
* Computes and returns the average elevation of all peaks in map,
* as described in part (b).
* Returns 0.0 if map contains no peaks.
/
public double averagePeakElevation() {
/
to be implemented in part (b) */
}

// Constructor and other instance variables/methods not shown
}



Part (a)


Write the isPeak method, which determines whether the cell at row r and column c is a local peak. A cell is a local peak if its elevation is strictly greater than each of its valid, directly adjacent neighbors (up, down, left, and right). Corner and edge cells only need to be compared against their existing valid neighbors.



For example, suppose map contains the following values:




0123
01218159
11014228
22011167



  • isPeak(0, 1) returns true because 18 is strictly greater than all valid neighbors: 12 (left), 15 (right), and 14 (below).

  • isPeak(1, 2) returns true because 22 is strictly greater than 15 (above), 16 (below), 14 (left), and 8 (right).

  • isPeak(2, 0) returns true because 20 is strictly greater than 10 (above) and 11 (right).

  • isPeak(0, 0) returns false because 12 is not greater than 18 (right).



/**
* Returns true if the cell at row r and column c is a local peak;
* false otherwise, as described in part (a).
* Preconditions: r is a valid row index in map.
* c is a valid column index in map.
*/
public boolean isPeak(int r, int c)



Part (b)


Write the averagePeakElevation method, which computes and returns the average elevation of all peak cells in map as a double. If there are no peaks in map, the method returns 0.0.



Assume that isPeak works as intended, regardless of what you wrote in part (a). You must call isPeak appropriately to receive full credit.



/**
* Computes and returns the average elevation of all peaks in map,
* as described in part (b).
* Returns 0.0 if map contains no peaks.
*/
public double averagePeakElevation()
查看答案详解

解题

Canonical Solution



Part (a)


public boolean isPeak(int r, int c) {
int val = map[r][c];
if (r > 0 && map[r - 1][c] >= val) {
return false;
}
if (r < map.length - 1 && map[r + 1][c] >= val) {
return false;
}
if (c > 0 && map[r][c - 1] >= val) {
return false;
}
if (c < map[0].length - 1 && map[r][c + 1] >= val) {
return false;
}
return true;
}

Part (b)


public double averagePeakElevation() {
int count = 0;
int sum = 0;
for (int r = 0; r < map.length; r++) {
for (int c = 0; c < map[r].length; c++) {
if (isPeak(r, c)) {
count++;
sum += map[r][c];
}
}
}
if (count == 0) {
return 0.0;
}
return (double) sum / count;
}

评分标准

Part (a): isPeak (4 points)



  1. 1 point - Accesses the value of the target cell at map[r][c] and compares it to adjacent neighbor cells (up, down, left, right).

  2. 1 point - Properly guards against out-of-bounds array access for all four neighbors (checks bounds before accessing adjacent cells).

  3. 1 point - Correctly determines if any adjacent neighbor is greater than or equal to the target cell's elevation.

  4. 1 point (algorithm) - Returns true if and only if all existing adjacent neighbors are strictly smaller than map[r][c], and returns false otherwise (without bounds errors).



Part (b): averagePeakElevation (5 points)



  1. 1 point - Traverses all elements of map in a nested loop with no bounds errors.

  2. 1 point - Calls isPeak(r, c) with appropriate row and column arguments inside the loop.

  3. 1 point - Accumulates the sum and counts the number of identified peaks.

  4. 1 point - Handles the edge case of zero peaks (returns 0.0).

  5. 1 point (algorithm) - Computes and returns the correct average as a double using floating-point division.

准备好测试自己了吗?

将这些笔记转化为考试练习。获取此课题的无限AI题目,即时批改及详细解析。

练习此课题

想知道自己有几分把握?

thinka 是 DSE 学生在用的 AI 练习应用,提供无限量练习题、即时自动批改和详细解题步骤。超过 100,000 名学生用它确认自己是真的会,而不只是「以为会」。

想练更多同类题型?在 thinka 无限量刷题,即时知道答案。

免费开始练习