| 1 | 1 | class Garden: |
| 2 | 2 | def __init__(self, diagram: str, students: list[str] | None = None) -> None: |
| 3 | | pass |
| 3 | # Edge Case: Empty diagram input |
| 4 | if not diagram: |
| 5 | self.rows = ["", ""] |
| 6 | else: |
| 7 | self.rows = diagram.split('\n') |
| 8 | # Edge Case: Diagram with only one row |
| 9 | if len(self.rows) == 1: |
| 10 | self.rows.append("") |
| 11 | |
| 12 | # Edge Case: Mismatched row lengths - pad shorter row with empty spaces |
| 13 | if len(self.rows) >= 2: |
| 14 | max_length = max(len(self.rows[0]), len(self.rows[1])) |
| 15 | # Only pad if both rows have content, otherwise keep empty rows as empty |
| 16 | if self.rows[0] and self.rows[1]: |
| 17 | self.rows[0] = self.rows[0].ljust(max_length) |
| 18 | self.rows[1] = self.rows[1].ljust(max_length) |
| 19 | elif self.rows[0] and not self.rows[1]: |
| 20 | # Keep second row empty if it was originally empty |
| 21 | pass |
| 22 | elif not self.rows[0] and self.rows[1]: |
| 23 | # Keep first row empty if it was originally empty |
| 24 | pass |
| 25 | |
| 26 | # Edge Case: No students provided - use default list |
| 27 | if students is None: |
| 28 | self.students = ["Alice", "Bob", "Charlie", "David", "Eve", "Fred", |
| 29 | "Ginny", "Harriet", "Ileana", "Joseph", "Kincaid", "Larry"] |
| 30 | else: |
| 31 | # Edge Case: Custom student list - sort alphabetically |
| 32 | self.students = sorted(students) |
| 33 | |
| 34 | # Edge Case: Duplicate student names in custom list |
| 35 | if students is not None and len(self.students) != len(set(self.students)): |
| 36 | # Keep only first occurrence of each name |
| 37 | seen = set() |
| 38 | unique_students = [] |
| 39 | for student in self.students: |
| 40 | if student not in seen: |
| 41 | unique_students.append(student) |
| 42 | seen.add(student) |
| 43 | self.students = unique_students |
| 4 | 44 | |
| 5 | 45 | def plants(self, student: str) -> list[str]: |
| 6 | | pass |
| 46 | # Edge Case: Invalid student name |
| 47 | if student not in self.students: |
| 48 | raise ValueError(f"Student {student} not found in the roster") |
| 49 | |
| 50 | # Find student's position |
| 51 | student_index = self.students.index(student) |
| 52 | |
| 53 | # Each student gets 2 consecutive cups in each row |
| 54 | start_position = student_index * 2 |
| 55 | |
| 56 | # Edge Case: Empty second row (single row garden) |
| 57 | if not self.rows[1]: |
| 58 | raise ValueError("Cannot get plants from empty second row") |
| 59 | |
| 60 | # Edge Case: Insufficient plants for all students |
| 61 | if start_position >= len(self.rows[0]) or (self.rows[1] and start_position >= len(self.rows[1])): |
| 62 | # Return whatever plants are available, padding with empty if necessary |
| 63 | result = [] |
| 64 | # Get plants from first row |
| 65 | for i in range(2): |
| 66 | pos = start_position + i |
| 67 | if pos < len(self.rows[0]): |
| 68 | if self.rows[0][pos] in "GCVR": |
| 69 | result.append(self.rows[0][pos]) |
| 70 | else: |
| 71 | raise ValueError(f"Invalid plant code: {self.rows[0][pos]}") |
| 72 | else: |
| 73 | raise ValueError("Not enough plants in the first row for all students") |
| 74 | |
| 75 | # Get plants from second row |
| 76 | for i in range(2): |
| 77 | pos = start_position + i |
| 78 | if pos < len(self.rows[1]): |
| 79 | if self.rows[1][pos] in "GCVR": |
| 80 | result.append(self.rows[1][pos]) |
| 81 | else: |
| 82 | raise ValueError(f"Invalid plant code: {self.rows[1][pos]}") |
| 83 | else: |
| 84 | raise ValueError("Not enough plants in the second row for all students") |
| 85 | |
| 86 | # Convert to full names |
| 87 | plant_names = [] |
| 88 | for code in result: |
| 89 | if code == 'G': |
| 90 | plant_names.append("Grass") |
| 91 | elif code == 'C': |
| 92 | plant_names.append("Clover") |
| 93 | elif code == 'V': |
| 94 | plant_names.append("Violets") |
| 95 | elif code == 'R': |
| 96 | plant_names.append("Radishes") |
| 97 | return plant_names |
| 98 | |
| 99 | # Normal case - get the 4 plants (2 from each row) |
| 100 | plant_codes = [] |
| 101 | # Get 2 plants from first row |
| 102 | if start_position + 1 < len(self.rows[0]): |
| 103 | plant_codes.append(self.rows[0][start_position]) |
| 104 | plant_codes.append(self.rows[0][start_position + 1]) |
| 105 | else: |
| 106 | # Not enough plants in first row |
| 107 | raise ValueError("Not enough plants in the first row for all students") |
| 108 | |
| 109 | # Get 2 plants from second row (if it exists and has enough plants) |
| 110 | if self.rows[1] and start_position + 1 < len(self.rows[1]): |
| 111 | plant_codes.append(self.rows[1][start_position]) |
| 112 | plant_codes.append(self.rows[1][start_position + 1]) |
| 113 | elif not self.rows[1]: |
| 114 | # Second row is empty - this is a single row garden |
| 115 | raise ValueError("Cannot get plants from empty second row") |
| 116 | else: |
| 117 | # Not enough plants in second row |
| 118 | raise ValueError("Not enough plants in the second row for all students") |
| 119 | |
| 120 | # Edge Case: Invalid plant encoding characters |
| 121 | plant_names = [] |
| 122 | for code in plant_codes: |
| 123 | if code == 'G': |
| 124 | plant_names.append("Grass") |
| 125 | elif code == 'C': |
| 126 | plant_names.append("Clover") |
| 127 | elif code == 'V': |
| 128 | plant_names.append("Violets") |
| 129 | elif code == 'R': |
| 130 | plant_names.append("Radishes") |
| 131 | else: |
| 132 | # Handle invalid characters by raising error |
| 133 | raise ValueError(f"Invalid plant code: {code}") |
| 134 | |
| 135 | return plant_names |
| 136 | |
| 137 | # Handled Edge Cases: empty diagram input, mismatched row lengths, invalid student names, insufficient plants for all students, non-alphabetical custom student list, duplicate student names, invalid plant encoding characters, diagram with only one row |