Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
A table is a directory of files written over two years by three different versions of the producer. Reading it needs one schema, and the current code merges the per-file schemas with dict.update — so the last file read decides every column's type, and a scan fails at whichever row disagrees.
Write unify_schemas(files). Return the schema and everything that cannot be unified.
Function to write
unify_schemas(files: list[dict]) -> dictA dict with the unified schema, the fields that conflict with all their declared types, and the partial fields.
How to approach it
Collect every declaration per field first, then fold the promotions across them.
Sample cases
+ 2 held back until you submit
four monthly files
A chain of widenings, a case difference, a field only some files have, and a string-versus-int conflict.
Input
Argument 1
[
{
'path': '2026-01.parquet',
'schema': {
'id': 'int32',
'amount': 'int64',
'ts': 'date',
'note': 'string'
}
},
{
'path': '2026-02.parquet',
'schema': {
'id': 'int64',
'amount': 'float64',
'ts': 'timestamp'
}
},
{
'path': '2026-03.parquet',
'schema': {
'id': 'int64',
'amount': 'float64',
'ts': 'TIMESTAMP',
'note': 'int64'
}
},
{
'path': '2026-04.parquet',
'schema': {
'id': 'int32',
'amount': 'float32',
'channel': 'string'
}
}
]Returns
{
'schema': {
'amount': 'float64',
'channel': 'string',
'id': 'int64',
'ts': 'timestamp'
},
'conflicts': [
{
'field': 'note',
'types': [
'int64',
'string'
]
}
],
'partial_fields': [
'channel',
'ts'
]
}no files
An empty table has an empty schema rather than raising on the first file.
Input
Argument 1
[] (empty list)
Returns
{
'schema': {},
'conflicts': [],
'partial_fields': []
}one file
A single file needs no unification, and nothing is partial when every file has the field.
Input
Argument 1
[
{
'path': 'only.parquet',
'schema': {
'id': 'int32'
}
}
]Returns
{
'schema': {
'id': 'int32'
},
'conflicts': [],
'partial_fields': []
}Constraints
partial_fields.conflicts and partial_fields.Worked example
The amount column is int64 in January, float64 in February and March, and float32 in April. Unifying pairwise from the start gives int64, then float64, then float64 again — one type that reads every file. Taking the last file's declaration would give float32, and the January values that do not fit in 24 bits of mantissa would be read back subtly wrong, with no error anywhere.
The note column is string in January and int64 in March. There is no type that reads both, and there is no honest default: choosing string means the March values are stringified, choosing int64 means January fails to parse. Reporting it as a conflict and excluding it is the only answer that does not silently corrupt one of the two months, and it is a decision a human has to make.
What this tests
Type promotion as a lattice rather than a preference order, and the discipline to refuse rather than guess. The reason a lakehouse table format keeps a schema at all is precisely that inferring one per file produces exactly this problem.
unify_schemas(files: list[dict]) -> dictSubmit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.