diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel b/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel index 02fc857df..50984fe37 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel @@ -60,11 +60,13 @@ java_library( ":default_optimizer_constants", "//:auto_value", "//bundle:cel", + "//checker:standard_decl", "//common:cel_ast", "//common:cel_source", "//common:compiler_common", "//common:mutable_ast", "//common:mutable_source", + "//common:operator", "//common/ast", "//common/ast:cel_block", "//common/ast:mutable_expr", diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java index 74794cda5..7c29938e9 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java @@ -26,15 +26,22 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.base.Verify; +import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimaps; +import com.google.common.collect.Multiset; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.google.errorprone.annotations.CanIgnoreReturnValue; import dev.cel.bundle.Cel; import dev.cel.bundle.CelBuilder; +import dev.cel.checker.CelStandardDeclarations.StandardFunction.Overload.Arithmetic; +import dev.cel.checker.CelStandardDeclarations.StandardFunction.Overload.BooleanOperator; +import dev.cel.checker.CelStandardDeclarations.StandardFunction.Overload.Comparison; +import dev.cel.checker.CelStandardDeclarations.StandardFunction.Overload.Relation; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelMutableAst; import dev.cel.common.CelMutableSource; @@ -44,6 +51,7 @@ import dev.cel.common.CelSource.Extension.Version; import dev.cel.common.CelValidationException; import dev.cel.common.CelVarDecl; +import dev.cel.common.Operator; import dev.cel.common.ast.CelBlock; import dev.cel.common.ast.CelExpr; import dev.cel.common.ast.CelExpr.CelCall; @@ -51,8 +59,15 @@ import dev.cel.common.ast.CelExpr.CelList; import dev.cel.common.ast.CelExpr.ExprKind.Kind; import dev.cel.common.ast.CelMutableExpr; +import dev.cel.common.ast.CelMutableExpr.CelMutableCall; +import dev.cel.common.ast.CelMutableExpr.CelMutableComprehension; import dev.cel.common.ast.CelMutableExpr.CelMutableIdent; +import dev.cel.common.ast.CelMutableExpr.CelMutableList; +import dev.cel.common.ast.CelMutableExpr.CelMutableMap; +import dev.cel.common.ast.CelMutableExpr.CelMutableSelect; +import dev.cel.common.ast.CelMutableExpr.CelMutableStruct; import dev.cel.common.ast.CelMutableExprConverter; +import dev.cel.common.ast.CelReference; import dev.cel.common.navigation.CelNavigableExpr; import dev.cel.common.navigation.CelNavigableExprUtil; import dev.cel.common.navigation.CelNavigableMutableAst; @@ -65,8 +80,10 @@ import dev.cel.optimizer.CelAstOptimizer; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -173,7 +190,9 @@ private OptimizationResult optimizeUsingCelBlock(CelAbstractSyntaxTree ast, Cel for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) { CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify); - ImmutableList cseCandidates = getCseCandidates(navAst); + ValueNumberer valueNumberer = + new ValueNumberer(navAst.getRoot().expr(), ast.getReferenceMap()); + ImmutableList cseCandidates = getCseCandidates(navAst, valueNumberer); if (cseCandidates.isEmpty()) { break; } @@ -390,25 +409,50 @@ private static void replaceWithBlockIdent( expr.setIdent(CelMutableIdent.create(blockIdentifier)); } - private ImmutableList getCseCandidates(CelNavigableMutableAst navAst) { + private ImmutableList getCseCandidates( + CelNavigableMutableAst navAst, ValueNumberer valueNumberer) { Set ineligibleExprs = getIneligibleExprsFromComprehensionBranches(navAst); ImmutableList allNodes = navAst.getRoot().allNodes(TraversalOrder.PRE_ORDER).collect(toImmutableList()); ImmutableListMultimap nodesByHeight = Multimaps.index(allNodes, CelNavigableMutableExpr::height); - HashSet semanticallyEqualNodes = new HashSet<>(); + // Loop-invariant subexpressions are extracted even if they occur once: block slots are lazily + // memoized, so they then run at most once and only if reached, instead of once per iteration. + @SuppressWarnings("ValueClassIdentity") // Integer values are only unboxed, never compared. + IdentityHashMap loopDepths = new IdentityHashMap<>(); for (CelNavigableMutableExpr node : allNodes) { - ImmutableList sameHeightNodes = nodesByHeight.get(node.height()); - if (sameHeightNodes.size() < 2 || !canEliminate(node, ineligibleExprs)) { + if (node.getKind().equals(Kind.COMPREHENSION)) { + CelNavigableMutableExpr.fromExpr(node.expr().comprehension().loopStep()) + .allNodes() + .forEach(step -> loopDepths.merge(step.expr(), 1, Integer::sum)); + } + } + // Only hoisting needs these, and computing them walks every node's subtree. + Set eligibleExprs = Sets.newIdentityHashSet(); + Multiset vnCounts = HashMultiset.create(); + if (!loopDepths.isEmpty()) { + for (CelNavigableMutableExpr node : allNodes) { + if (canEliminate(node, ineligibleExprs)) { + eligibleExprs.add(node.expr()); + vnCounts.add(valueNumberer.vnOf(node.expr())); + } + } + } + Set seenVns = new HashSet<>(); + for (CelNavigableMutableExpr node : allNodes) { + boolean inLoopStep = loopDepths.containsKey(node.expr()); + if ((!inLoopStep && nodesByHeight.get(node.height()).size() < 2) + || !canEliminate(node, ineligibleExprs)) { continue; } - // Normalize the expr to test semantic equivalence. - CelMutableExpr normalizedExpr = normalizeForEquality(node.expr()); - if (!semanticallyEqualNodes.add(normalizedExpr)) { - return sameHeightNodes.stream() + CelNavigableMutableExpr target = + inLoopStep ? hoistTarget(node, loopDepths, vnCounts, valueNumberer, eligibleExprs) : node; + int vn = valueNumberer.vnOf(target.expr()); + if (!seenVns.add(vn) || inLoopStep) { + return nodesByHeight.get(target.height()).stream() .filter(candidate -> canEliminate(candidate, ineligibleExprs)) .map(CelNavigableMutableExpr::expr) - .filter(expr -> normalizeForEquality(expr).equals(normalizedExpr)) + .filter(expr -> valueNumberer.vnOf(expr) == vn) .collect(toImmutableList()); } } @@ -416,6 +460,47 @@ private ImmutableList getCseCandidates(CelNavigableMutableAst na return ImmutableList.of(); } + // Slots are never revisited, so before hoisting `node` this first hoists any eligible descendant + // that also occurs outside of it, or that is invariant to a loop nested inside it. + private static CelNavigableMutableExpr hoistTarget( + CelNavigableMutableExpr node, + IdentityHashMap loopDepths, + Multiset vnCounts, + ValueNumberer valueNumberer, + Set eligibleExprs) { + ImmutableList descendants = + node.descendants(TraversalOrder.PRE_ORDER) + .filter(d -> eligibleExprs.contains(d.expr())) + .collect(toImmutableList()); + Multiset innerVnCounts = HashMultiset.create(); + descendants.forEach(d -> innerVnCounts.add(valueNumberer.vnOf(d.expr()))); + // Equivalent copies of `node` are extracted along with it, so occurrences inside them are fine. + int copies = vnCounts.count(valueNumberer.vnOf(node.expr())); + int depth = loopDepths.get(node.expr()); + return descendants.stream() + .filter( + d -> { + int vn = valueNumberer.vnOf(d.expr()); + return vnCounts.count(vn) > innerVnCounts.count(vn) * copies + || loopDepths.get(d.expr()) > depth; + }) + .findFirst() + .map(d -> hoistTarget(d, loopDepths, vnCounts, valueNumberer, eligibleExprs)) + .orElse(node); + } + + // The planner accumulates `@ac + [elem]` steps (map, filter) in place, so `[elem]` is not + // extracted. + private static boolean isAccumulation(CelMutableExpr expr) { + if (!expr.getKind().equals(Kind.CALL) + || !expr.call().function().equals(Operator.ADD.getFunction())) { + return false; + } + CelMutableExpr accu = expr.call().args().get(0); + return accu.getKind().equals(Kind.IDENT) + && accu.ident().name().startsWith(MANGLED_COMPREHENSION_ACCU_VAR_PREFIX); + } + private boolean canEliminate( CelNavigableMutableExpr navigableExpr, Set ineligibleExprs) { return !navigableExpr.getKind().equals(Kind.CONSTANT) @@ -471,6 +556,12 @@ private static Set getIneligibleExprsFromComprehensionBranches( .allNodes()) .map(CelNavigableMutableExpr::expr) .forEach(ineligibleExprs::add)); + navAst + .getRoot() + .allNodes() + .map(CelNavigableMutableExpr::expr) + .filter(SubexpressionOptimizer::isAccumulation) + .forEach(expr -> ineligibleExprs.add(expr.call().args().get(1))); return ineligibleExprs; } @@ -488,17 +579,146 @@ private boolean containsEliminableFunctionOnly(CelNavigableMutableExpr navigable }); } - /** - * Converts the {@link CelMutableExpr} to make it suitable for performing a semantically equals - * check. - * - *

Specifically, this will deep copy the mutable expr then set all expr IDs in the expression - * tree to 0. - */ - private CelMutableExpr normalizeForEquality(CelMutableExpr mutableExpr) { - CelMutableExpr copiedExpr = CelMutableExpr.newInstance(mutableExpr); + // Assigns equal value numbers to equivalent subexpressions, including commuted and converse calls + // with only standard overloads. If both operands fail, either error may be reported, which CEL's + // unspecified evaluation order permits. + private static final class ValueNumberer { + private static final ImmutableMap SWAPPED_FUNCTIONS = + ImmutableMap.builder() + .put(Operator.ADD.getFunction(), Operator.ADD.getFunction()) + .put(Operator.MULTIPLY.getFunction(), Operator.MULTIPLY.getFunction()) + .put(Operator.EQUALS.getFunction(), Operator.EQUALS.getFunction()) + .put(Operator.NOT_EQUALS.getFunction(), Operator.NOT_EQUALS.getFunction()) + .put(Operator.LOGICAL_AND.getFunction(), Operator.LOGICAL_AND.getFunction()) + .put(Operator.LOGICAL_OR.getFunction(), Operator.LOGICAL_OR.getFunction()) + .put(Operator.GREATER.getFunction(), Operator.LESS.getFunction()) + .put(Operator.GREATER_EQUALS.getFunction(), Operator.LESS_EQUALS.getFunction()) + .buildOrThrow(); + private static final ImmutableSet SWAPPABLE_OVERLOAD_IDS = + Stream.concat( + Stream.of( + Arithmetic.ADD_INT64, + Arithmetic.ADD_UINT64, + Arithmetic.ADD_DOUBLE, + Arithmetic.ADD_DURATION_DURATION, + Arithmetic.ADD_TIMESTAMP_DURATION, + Arithmetic.ADD_DURATION_TIMESTAMP, + Arithmetic.MULTIPLY_INT64, + Arithmetic.MULTIPLY_UINT64, + Arithmetic.MULTIPLY_DOUBLE, + Relation.EQUALS, + Relation.NOT_EQUALS, + BooleanOperator.LOGICAL_AND, + BooleanOperator.LOGICAL_OR), + EnumSet.allOf(Comparison.class).stream()) + .map(overload -> overload.celOverloadDecl().overloadId()) + .collect(toImmutableSet()); - return astMutator.clearExprIds(copiedExpr); + private final ImmutableMap references; + private final Map, Integer> keyToVn; + private final IdentityHashMap exprToVn; + + private int vnOf(CelMutableExpr expr) { + return Verify.verifyNotNull(exprToVn.get(expr)); + } + + private int computeVn(CelMutableExpr expr) { + ImmutableList key = buildKey(expr); + int vn = keyToVn.computeIfAbsent(key, k -> keyToVn.size()); + exprToVn.put(expr, vn); + return vn; + } + + private ImmutableList computeVns(List exprs) { + ImmutableList.Builder vns = ImmutableList.builderWithExpectedSize(exprs.size()); + for (CelMutableExpr expr : exprs) { + vns.add(computeVn(expr)); + } + return vns.build(); + } + + private ImmutableList buildKey(CelMutableExpr expr) { + switch (expr.getKind()) { + case CONSTANT: + return ImmutableList.of(Kind.CONSTANT, expr.constant()); + case IDENT: + // Runs after identifiers are mangled. + return ImmutableList.of(Kind.IDENT, expr.ident().name()); + case SELECT: + CelMutableSelect select = expr.select(); + return ImmutableList.of( + Kind.SELECT, computeVn(select.operand()), select.field(), select.testOnly()); + case CALL: + CelMutableCall call = expr.call(); + String function = call.function(); + // VNs are non-negative, so -1 marks a global call. + int targetVn = call.target().map(this::computeVn).orElse(-1); + ImmutableList argVns = computeVns(call.args()); + // Keyed even when no swap applies (e.g. _<_), so a call that also resolves to custom + // overloads (x < 5 on dyn) never merges with a canonicalized standard-only one (5 > x). + boolean swappable = hasOnlySwappableOverloads(expr.id()); + String swapped = SWAPPED_FUNCTIONS.get(function); + if (swappable + && swapped != null + && (!swapped.equals(function) || argVns.get(0) > argVns.get(1))) { + function = swapped; + argVns = argVns.reverse(); + } + return ImmutableList.of(Kind.CALL, targetVn, function, argVns, swappable); + case LIST: + CelMutableList list = expr.list(); + return ImmutableList.of( + Kind.LIST, computeVns(list.elements()), ImmutableList.copyOf(list.optionalIndices())); + case MAP: + CelMutableMap map = expr.map(); + ImmutableList.Builder entryVns = + ImmutableList.builderWithExpectedSize(map.entries().size()); + for (CelMutableMap.Entry entry : map.entries()) { + entryVns.add( + ImmutableList.of( + computeVn(entry.key()), computeVn(entry.value()), entry.optionalEntry())); + } + return ImmutableList.of(Kind.MAP, entryVns.build()); + case STRUCT: + CelMutableStruct struct = expr.struct(); + ImmutableList.Builder fieldVns = + ImmutableList.builderWithExpectedSize(struct.entries().size()); + for (CelMutableStruct.Entry entry : struct.entries()) { + fieldVns.add( + ImmutableList.of( + entry.fieldKey(), computeVn(entry.value()), entry.optionalEntry())); + } + return ImmutableList.of(Kind.STRUCT, struct.messageName(), fieldVns.build()); + case COMPREHENSION: + CelMutableComprehension comp = expr.comprehension(); + return ImmutableList.of( + Kind.COMPREHENSION, + comp.iterVar(), + comp.iterVar2(), + comp.accuVar(), + computeVn(comp.iterRange()), + computeVn(comp.accuInit()), + computeVn(comp.loopCondition()), + computeVn(comp.loopStep()), + computeVn(comp.result())); + default: + throw new IllegalArgumentException("Unexpected ExprKind: " + expr.getKind()); + } + } + + private boolean hasOnlySwappableOverloads(long id) { + ImmutableList overloadIds = references.get(id).overloadIds(); + // Fail closed: containsAll is vacuously true for an empty list. + return !overloadIds.isEmpty() && SWAPPABLE_OVERLOAD_IDS.containsAll(overloadIds); + } + + @SuppressWarnings("ValueClassIdentity") // Integer values are only unboxed, never compared. + private ValueNumberer(CelMutableExpr root, ImmutableMap references) { + this.references = references; + this.keyToVn = new HashMap<>(); + this.exprToVn = new IdentityHashMap<>(); + computeVn(root); + } } /** Options to configure how Common Subexpression Elimination behave. */ diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index ffe79faf1..2361958ca 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static dev.cel.common.CelOverloadDecl.newGlobalOverload; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; @@ -95,6 +96,8 @@ private static Cel setupCelEnv(CelBuilder celBuilder) { TestAllTypes.newBuilder() .setSingleInt64(3L) .setSingleInt32(5) + .addAllRepeatedInt64(ImmutableList.of(1L, 2L, 3L)) + .addRepeatedInt32(2) .setOneofType( NestedTestAllTypes.newBuilder() .setPayload( @@ -403,7 +406,37 @@ private enum CseTestCase { "pure_custom_func(msg.oneof_type.payload.single_int64) +" + " pure_custom_func(msg.oneof_type.payload.single_int32) +" + " pure_custom_func(msg.oneof_type.payload.single_int64) +" - + " pure_custom_func(msg.single_int64)"); + + " pure_custom_func(msg.single_int64)"), + VALUE_NUMBERING_COMMUTATIVE_ADD_CONVERSE_RELATION_LOGICAL_AND( + "(msg.single_int64 + msg.single_int32 > 5 && msg.oneof_type.payload.single_int64 <" + + " msg.single_int64 + msg.single_int32) == (msg.single_int32 + msg.single_int64 >" + + " msg.oneof_type.payload.single_int64 && 5 < msg.single_int32 + msg.single_int64)"), + VALUE_NUMBERING_COMMUTATIVE_MULTIPLY_EQUALITY_LOGICAL_OR( + "(msg.oneof_type.payload.single_int32 * msg.single_int64 == 24 || msg.single_int32 !=" + + " msg.oneof_type.payload.single_int64) && (msg.oneof_type.payload.single_int64 !=" + + " msg.single_int32 || 24 == msg.single_int64 * msg.oneof_type.payload.single_int32)"), + HOIST_NESTED_COMPREHENSION("msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == 2))"), + HOIST_INVARIANT_ARITHMETIC( + "msg.repeated_int64.exists(i, i == msg.single_int64 * 2 + msg.single_int32)"), + HOIST_ZERO_TRIP_ERROR_NOT_EVALUATED( + "msg.repeated_nested_message.exists(m, m.bb == 1 / (msg.single_int32 - 5))"), + HOIST_MAP_ACCUMULATION_PRESERVED("msg.repeated_int64.map(i, msg.single_int64 * 2)"), + HOIST_LIST_LITERAL("msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32])"), + HOIST_LIST_APPENDED_TO_ITER_VAR("[[1], [2]].map(l, l + [msg.single_int64])"), + HOIST_INVARIANT_INSIDE_DUPLICATE( + "msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) ||" + + " msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32])"), + HOIST_INVARIANT_OF_NESTED_COMPREHENSION( + "msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == msg.single_int64 * 2))"), + HOIST_SHARED_TERMS_ONCE( + "msg.repeated_int64.exists(i, i == msg.single_int64 + msg.single_int32 +" + + " msg.single_sint64) && [msg.single_int64, msg.single_int32, msg.single_sint64]" + + ".size() > 0"), + HOIST_SHARED_WITH_ACCUMULATED_LIST( + "msg.repeated_int64.exists(i, i in [msg.single_int64]) &&" + + " msg.repeated_int64.map(i, msg.single_int64).size() > 0"), + ; + private final String source; CseTestCase(String source) { diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java index cba16b6df..192a8d125 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java @@ -79,8 +79,9 @@ private static Cel setupCelEnv(CelBuilder celBuilder) { .populateMacroCalls(true) .enableHeterogeneousNumericComparisons(true) .build()) - .addCompilerLibraries(CelExtensions.bindings(), CelExtensions.strings()) - .addRuntimeLibraries(CelExtensions.strings()) + .addCompilerLibraries( + CelExtensions.bindings(), CelExtensions.strings(), CelExtensions.optional()) + .addRuntimeLibraries(CelExtensions.strings(), CelExtensions.optional()) .addFunctionDeclarations( CelFunctionDecl.newFunctionDeclaration( "non_pure_custom_func", @@ -756,12 +757,12 @@ public void cse_nestedMacro_noOp_assertAstIdCorrectness() throws Exception { .addAstOptimizers(SubexpressionOptimizer.getInstance()) .build(); CelAbstractSyntaxTree ast = - cel.compile("[{}, {\"a\": 1}, {\"b\": 2}].filter(m, has(x.a))").getAst(); + cel.compile("[{}, {\"a\": 1}, {\"b\": 2}].filter(m, has(m.a))").getAst(); CelAbstractSyntaxTree optimizedAst = celOptimizer.optimize(ast); assertThat(CEL_UNPARSER.unparse(optimizedAst)) - .isEqualTo("[{}, {\"a\": 1}, {\"b\": 2}].filter(m, has(x.a))"); + .isEqualTo("[{}, {\"a\": 1}, {\"b\": 2}].filter(m, has(m.a))"); assertThat(optimizedAst).isSameInstanceAs(ast); } @@ -796,8 +797,8 @@ public void cse_nestedMacro_withOptimization_assertAstIdCorrectness() throws Exc assertThat(CEL_UNPARSER.unparse(optimizedAst)) .isEqualTo( - "cel.@block([[{}, {\"a\": 1}, {\"b\": 2}].filter(@it:0:0, has(x.a))], @index0 ==" - + " @index0)"); + "cel.@block([has(x.a), [{}, {\"a\": 1}, {\"b\": 2}].filter(@it:0:0, @index0)], @index1" + + " == @index1)"); } @Test @@ -822,6 +823,175 @@ public void optimize_afterSelectOptimizer_throwsException( .contains("SubexpressionOptimizer must run before SelectOptimizer."); } + private enum ValueNumberingTestCase { + COMMUTATIVE_INT_ADD( + "(msg.single_int64 + msg.single_int32) * (msg.single_int32 + msg.single_int64)", + "cel.@block([msg.single_int64 + msg.single_int32], @index0 * @index0)"), + COMMUTATIVE_UINT_MULTIPLY( + "(msg.single_uint64 * msg.single_uint32) + (msg.single_uint32 * msg.single_uint64)", + "cel.@block([msg.single_uint64 * msg.single_uint32], @index0 + @index0)"), + COMMUTATIVE_DOUBLE_ADD( + "(msg.single_double + 1.5) * (1.5 + msg.single_double)", + "cel.@block([msg.single_double + 1.5], @index0 * @index0)"), + COMMUTATIVE_DURATION_TIMESTAMP_ADD( + "(msg.single_duration + msg.single_timestamp) == (msg.single_timestamp +" + + " msg.single_duration)", + "cel.@block([msg.single_duration + msg.single_timestamp], @index0 == @index0)"), + NON_COMMUTATIVE_INT_SUBTRACT_PRESERVED( + "(msg.single_int64 - msg.single_int32) == (msg.single_int32 - msg.single_int64)", + "cel.@block([msg.single_int32, msg.single_int64], @index1 - @index0 == @index0 - @index1)"), + NON_COMMUTATIVE_STRING_CONCAT_PRESERVED( + "(msg.single_string + \"a\") == (\"a\" + msg.single_string)", + "cel.@block([msg.single_string], @index0 + \"a\" == \"a\" + @index0)"), + NON_COMMUTATIVE_DYN_ADD_PRESERVED( + "(dyn(msg.single_string) + dyn(\"a\")) == (dyn(\"a\") + dyn(msg.single_string))", + "cel.@block([dyn(\"a\"), dyn(msg.single_string)], @index1 + @index0 == @index0 +" + + " @index1)"), + COMMUTATIVE_EQUALS( + "(msg.single_int64 == 1) && (1 == msg.single_int64)", + "cel.@block([msg.single_int64 == 1], @index0 && @index0)"), + COMMUTATIVE_NOT_EQUALS( + "(msg.single_int64 != 1) || (1 != msg.single_int64)", + "cel.@block([msg.single_int64 != 1], @index0 || @index0)"), + COMMUTATIVE_LOGICAL_AND( + "((msg.single_int64 == 1) && (msg.single_int32 == 2)) || ((msg.single_int32 == 2) &&" + + " (msg.single_int64 == 1))", + "cel.@block([msg.single_int64 == 1 && msg.single_int32 == 2], @index0 || @index0)"), + COMMUTATIVE_LOGICAL_OR( + "((msg.single_int64 == 1) || (msg.single_int32 == 2)) && ((msg.single_int32 == 2) ||" + + " (msg.single_int64 == 1))", + "cel.@block([msg.single_int64 == 1 || msg.single_int32 == 2], @index0 && @index0)"), + RELATIONAL_CONVERSE_LESS_GREATER( + "(msg.single_int64 < msg.single_int32) && (msg.single_int32 > msg.single_int64)", + "cel.@block([msg.single_int64 < msg.single_int32], @index0 && @index0)"), + RELATIONAL_CONVERSE_LESS_EQUALS_GREATER_EQUALS( + "(msg.single_int64 <= msg.single_int32) && (msg.single_int32 >= msg.single_int64)", + "cel.@block([msg.single_int64 <= msg.single_int32], @index0 && @index0)"), + NOT_EQUALS_WITHOUT_SHARED_EQUALS_PRESERVED( + "[msg.single_int64 != 1, msg.single_int64 != 1, msg.single_int64 == 1]", + "cel.@block([msg.single_int64 != 1], [@index0, @index0, msg.single_int64 == 1])"), + OPTIONAL_LIST_AND_MAP_DISTINCT_VALUE_NUMBERS( + "([?optional.of(msg.single_int64)].size() == [optional.of(msg.single_int64)].size()) &&" + + " ({?\"k\": optional.of(msg.single_int64)}.size() == {\"k\":" + + " optional.of(msg.single_int64)}.size())", + "cel.@block([optional.of(msg.single_int64)], [?@index0].size() == [@index0].size() &&" + + " {?\"k\": @index0}.size() == {\"k\": @index0}.size())"), + ; + + private final String source; + private final String expectedUnparsed; + + ValueNumberingTestCase(String source, String expectedUnparsed) { + this.source = source; + this.expectedUnparsed = expectedUnparsed; + } + } + + @Test + public void cse_valueNumbering(@TestParameter ValueNumberingTestCase testCase) throws Exception { + CelAbstractSyntaxTree ast = cel.compile(testCase.source).getAst(); + CelOptimizer optimizer = + newCseOptimizer( + SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build()); + ImmutableMap input = + ImmutableMap.of( + "msg", + TestAllTypes.newBuilder() + .setSingleInt64(1L) + .setSingleInt32(2) + .setSingleUint64(3L) + .setSingleUint32(4) + .setSingleDouble(2.5) + .setSingleString("hello") + .build()); + + CelAbstractSyntaxTree optimizedAst = optimizer.optimize(ast); + + assertThat(CEL_UNPARSER.unparse(optimizedAst)).isEqualTo(testCase.expectedUnparsed); + assertThat(cel.createProgram(optimizedAst).eval(input)) + .isEqualTo(cel.createProgram(ast).eval(input)); + } + + @Test + public void cse_customOperatorOverloads_preservesSemantics( + @TestParameter({ + "(msg.single_string + msg.single_int64) == (msg.single_int64 + msg.single_string)", + "(msg.single_string > msg.single_int64) == (msg.single_int64 < msg.single_string)" + }) + String source) + throws Exception { + Cel cel = + this.cel + .toCelBuilder() + .addFunctionDeclarations( + CelFunctionDecl.newFunctionDeclaration( + "_+_", + newGlobalOverload( + "add_string_int", SimpleType.INT, SimpleType.STRING, SimpleType.INT), + newGlobalOverload( + "add_int_string", SimpleType.INT, SimpleType.INT, SimpleType.STRING)), + CelFunctionDecl.newFunctionDeclaration( + "_>_", + newGlobalOverload( + "greater_string_int", SimpleType.BOOL, SimpleType.STRING, SimpleType.INT)), + CelFunctionDecl.newFunctionDeclaration( + "_<_", + newGlobalOverload( + "less_int_string", SimpleType.BOOL, SimpleType.INT, SimpleType.STRING))) + .addFunctionBindings( + CelFunctionBinding.from( + "add_string_int", String.class, Long.class, (s, i) -> s.length() + i), + CelFunctionBinding.from( + "add_int_string", Long.class, String.class, (i, s) -> i * 100 + s.length()), + CelFunctionBinding.from( + "greater_string_int", String.class, Long.class, (s, i) -> s.length() > i), + CelFunctionBinding.from( + "less_int_string", Long.class, String.class, (i, s) -> i >= 0)) + .build(); + CelOptimizer optimizer = + CelOptimizerFactory.standardCelOptimizerBuilder(cel) + .addAstOptimizers(SubexpressionOptimizer.getInstance()) + .build(); + CelAbstractSyntaxTree ast = cel.compile(source).getAst(); + ImmutableMap input = + ImmutableMap.of( + "msg", TestAllTypes.newBuilder().setSingleString("a").setSingleInt64(1L).build()); + + CelAbstractSyntaxTree optimizedAst = optimizer.optimize(ast); + + assertThat(cel.createProgram(optimizedAst).eval(input)) + .isEqualTo(cel.createProgram(ast).eval(input)); + } + + @Test + public void cse_oneSidedCustomOverloadOnDyn_notMerged( + @TestParameter({"(x < 5) == (5 > x)", "(x + 1) == (1 + x)"}) String source) throws Exception { + // With x: dyn, only the left operand also resolves to the custom overload, so the right one is + // standard-only and swappable. The two must not share a value number. + Cel cel = + this.cel + .toCelBuilder() + .addFunctionDeclarations( + CelFunctionDecl.newFunctionDeclaration( + "_<_", + newGlobalOverload( + "less_string_int", SimpleType.BOOL, SimpleType.STRING, SimpleType.INT)), + CelFunctionDecl.newFunctionDeclaration( + "_+_", + newGlobalOverload( + "add_string_int", SimpleType.INT, SimpleType.STRING, SimpleType.INT))) + .build(); + CelOptimizer optimizer = + CelOptimizerFactory.standardCelOptimizerBuilder(cel) + .addAstOptimizers(SubexpressionOptimizer.getInstance()) + .build(); + CelAbstractSyntaxTree ast = cel.compile(source).getAst(); + + CelAbstractSyntaxTree optimizedAst = optimizer.optimize(ast); + + assertThat(CEL_UNPARSER.unparse(optimizedAst)).isEqualTo(CEL_UNPARSER.unparse(ast)); + } + /** * Converts AST containing cel.block related test functions to internal functions (e.g: cel.block * -> cel.@block) diff --git a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline index 1cceb0c60..dc7054428 100644 --- a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline @@ -314,4 +314,76 @@ Test case: CUSTOM_FUNCTION_ELIMINABLE Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) =====> Result: 31 -Unparsed: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) \ No newline at end of file +Unparsed: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) + +Test case: VALUE_NUMBERING_COMMUTATIVE_ADD_CONVERSE_RELATION_LOGICAL_AND +Source: (msg.single_int64 + msg.single_int32 > 5 && msg.oneof_type.payload.single_int64 < msg.single_int64 + msg.single_int32) == (msg.single_int32 + msg.single_int64 > msg.oneof_type.payload.single_int64 && 5 < msg.single_int32 + msg.single_int64) +=====> +Result: true +Unparsed: cel.@block([msg.single_int64 + msg.single_int32, @index0 > 5 && msg.oneof_type.payload.single_int64 < @index0], @index1 == @index1) + +Test case: VALUE_NUMBERING_COMMUTATIVE_MULTIPLY_EQUALITY_LOGICAL_OR +Source: (msg.oneof_type.payload.single_int32 * msg.single_int64 == 24 || msg.single_int32 != msg.oneof_type.payload.single_int64) && (msg.oneof_type.payload.single_int64 != msg.single_int32 || 24 == msg.single_int64 * msg.oneof_type.payload.single_int32) +=====> +Result: true +Unparsed: cel.@block([msg.oneof_type.payload, @index0.single_int32 * msg.single_int64 == 24 || msg.single_int32 != @index0.single_int64], @index1 && @index1) + +Test case: HOIST_NESTED_COMPREHENSION +Source: msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == 2)) +=====> +Result: true +Unparsed: cel.@block([msg.repeated_int32.exists(@it:0:0, @it:0:0 == 2)], msg.repeated_int64.all(@it:1:0, @index0)) + +Test case: HOIST_INVARIANT_ARITHMETIC +Source: msg.repeated_int64.exists(i, i == msg.single_int64 * 2 + msg.single_int32) +=====> +Result: false +Unparsed: cel.@block([msg.single_int64 * 2 + msg.single_int32], msg.repeated_int64.exists(@it:0:0, @it:0:0 == @index0)) + +Test case: HOIST_ZERO_TRIP_ERROR_NOT_EVALUATED +Source: msg.repeated_nested_message.exists(m, m.bb == 1 / (msg.single_int32 - 5)) +=====> +Result: false +Unparsed: cel.@block([1 / (msg.single_int32 - 5)], msg.repeated_nested_message.exists(@it:0:0, @it:0:0.bb == @index0)) + +Test case: HOIST_MAP_ACCUMULATION_PRESERVED +Source: msg.repeated_int64.map(i, msg.single_int64 * 2) +=====> +Result: [6, 6, 6] +Unparsed: cel.@block([msg.single_int64 * 2], msg.repeated_int64.map(@it:0:0, @index0)) + +Test case: HOIST_LIST_LITERAL +Source: msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) +=====> +Result: true +Unparsed: cel.@block([[msg.single_int64, msg.single_int32]], msg.repeated_int64.exists(@it:0:0, @it:0:0 in @index0)) + +Test case: HOIST_LIST_APPENDED_TO_ITER_VAR +Source: [[1], [2]].map(l, l + [msg.single_int64]) +=====> +Result: [[1, 3], [2, 3]] +Unparsed: cel.@block([[msg.single_int64]], [[1], [2]].map(@it:0:0, @it:0:0 + @index0)) + +Test case: HOIST_INVARIANT_INSIDE_DUPLICATE +Source: msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) || msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) +=====> +Result: true +Unparsed: cel.@block([[msg.single_int64, msg.single_int32], msg.repeated_int64.exists(@it:0:0, @it:0:0 in @index0)], @index1 || @index1) + +Test case: HOIST_INVARIANT_OF_NESTED_COMPREHENSION +Source: msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == msg.single_int64 * 2)) +=====> +Result: false +Unparsed: cel.@block([msg.single_int64 * 2, msg.repeated_int32.exists(@it:0:0, @it:0:0 == @index0)], msg.repeated_int64.all(@it:1:0, @index1)) + +Test case: HOIST_SHARED_TERMS_ONCE +Source: msg.repeated_int64.exists(i, i == msg.single_int64 + msg.single_int32 + msg.single_sint64) && [msg.single_int64, msg.single_int32, msg.single_sint64].size() > 0 +=====> +Result: false +Unparsed: cel.@block([msg.single_int64, msg.single_int32, msg.single_sint64, @index0 + @index1 + @index2], msg.repeated_int64.exists(@it:0:0, @it:0:0 == @index3) && [@index0, @index1, @index2].size() > 0) + +Test case: HOIST_SHARED_WITH_ACCUMULATED_LIST +Source: msg.repeated_int64.exists(i, i in [msg.single_int64]) && msg.repeated_int64.map(i, msg.single_int64).size() > 0 +=====> +Result: true +Unparsed: cel.@block([msg.single_int64, [@index0], msg.repeated_int64], @index2.exists(@it:0:0, @it:0:0 in @index1) && @index2.map(@it:0:1, @index0).size() > 0) \ No newline at end of file diff --git a/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline b/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline index fc5498563..2c88f173b 100644 --- a/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline +++ b/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline @@ -14,4 +14,4 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3])))))))) =====> Result: [[[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]]] -Unparsed: cel.@block([[1, 2, 3]], @index0.map(@it:7:0, @index0.map(@it:6:0, @index0.map(@it:5:0, @index0.map(@it:4:0, @index0.map(@it:3:0, @index0.map(@it:2:0, @index0.map(@it:1:0, @index0.map(@it:0:0, @index0))))))))) \ No newline at end of file +Unparsed: cel.@block([[1, 2, 3], @index0.map(@it:0:0, @index0), @index0.map(@it:1:0, @index1), @index0.map(@it:2:0, @index2), @index0.map(@it:3:0, @index3), @index0.map(@it:4:0, @index4), @index0.map(@it:5:0, @index5), @index0.map(@it:6:0, @index6)], @index0.map(@it:7:0, @index7)) \ No newline at end of file diff --git a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline index 9782b5dc2..becbcff4f 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline @@ -2104,89 +2104,92 @@ CALL [1] { CONSTANT [6] { value: 3 } } } - LIST [7] { + COMPREHENSION [7] { + iter_var: @it:0:0 + iter_range: { + IDENT [8] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [9] { + elements: { + } + } + } + loop_condition: { + CONSTANT [10] { value: true } + } + loop_step: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @ac:0:0 + } + LIST [13] { + elements: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @it:0:0 + } + CONSTANT [16] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [17] { + name: @ac:0:0 + } + } + } + LIST [18] { elements: { - CONSTANT [8] { value: 2 } - CONSTANT [9] { value: 3 } - CONSTANT [10] { value: 4 } + CONSTANT [19] { value: 2 } + CONSTANT [20] { value: 3 } + CONSTANT [21] { value: 4 } } } } } - CALL [11] { + CALL [22] { function: _==_ args: { - COMPREHENSION [12] { + COMPREHENSION [23] { iter_var: @it:1:0 iter_range: { - IDENT [13] { + IDENT [24] { name: @index0 } } accu_var: @ac:1:0 accu_init: { - LIST [14] { + LIST [25] { elements: { } } } loop_condition: { - CONSTANT [15] { value: true } + CONSTANT [26] { value: true } } loop_step: { - CALL [16] { + CALL [27] { function: _+_ args: { - IDENT [17] { + IDENT [28] { name: @ac:1:0 } - LIST [18] { + LIST [29] { elements: { - COMPREHENSION [19] { - iter_var: @it:0:0 - iter_range: { - IDENT [20] { - name: @index0 - } - } - accu_var: @ac:0:0 - accu_init: { - LIST [21] { - elements: { - } - } - } - loop_condition: { - CONSTANT [22] { value: true } - } - loop_step: { - CALL [23] { - function: _+_ - args: { - IDENT [24] { - name: @ac:0:0 - } - LIST [25] { - elements: { - CALL [26] { - function: _+_ - args: { - IDENT [27] { - name: @it:0:0 - } - CONSTANT [28] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [29] { - name: @ac:0:0 - } - } + IDENT [30] { + name: @index1 } } } @@ -2194,21 +2197,21 @@ CALL [1] { } } result: { - IDENT [30] { + IDENT [31] { name: @ac:1:0 } } } - LIST [31] { + LIST [32] { elements: { - IDENT [32] { - name: @index1 - } IDENT [33] { - name: @index1 + name: @index2 } IDENT [34] { - name: @index1 + name: @index2 + } + IDENT [35] { + name: @index2 } } } @@ -2219,122 +2222,134 @@ CALL [1] { Test case: NESTED_MACROS_2 Source: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] =====> -CALL [31] { - function: _==_ +CALL [1] { + function: cel.@block args: { - COMPREHENSION [30] { - iter_var: y - iter_range: { - LIST [1] { - elements: { - CONSTANT [2] { value: 1 } - CONSTANT [3] { value: 2 } - } - } - } - accu_var: @result - accu_init: { - LIST [24] { + LIST [2] { + elements: { + LIST [3] { elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } } } } - loop_condition: { - CONSTANT [25] { value: true } - } - loop_step: { - CALL [28] { - function: _+_ - args: { - IDENT [26] { - name: @result + } + CALL [7] { + function: _==_ + args: { + COMPREHENSION [8] { + iter_var: @it:1:0 + iter_range: { + LIST [9] { + elements: { + CONSTANT [10] { value: 1 } + CONSTANT [11] { value: 2 } + } } - LIST [27] { + } + accu_var: @ac:1:0 + accu_init: { + LIST [12] { elements: { - COMPREHENSION [23] { - iter_var: x - iter_range: { - LIST [6] { - elements: { - CONSTANT [7] { value: 1 } - CONSTANT [8] { value: 2 } - CONSTANT [9] { value: 3 } - } - } - } - accu_var: @result - accu_init: { - LIST [15] { - elements: { + } + } + } + loop_condition: { + CONSTANT [13] { value: true } + } + loop_step: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @ac:1:0 + } + LIST [16] { + elements: { + COMPREHENSION [17] { + iter_var: @it:0:0 + iter_range: { + IDENT [18] { + name: @index0 + } } - } - } - loop_condition: { - CONSTANT [16] { value: true } - } - loop_step: { - CALL [21] { - function: _?_:_ - args: { - CALL [13] { - function: _==_ - args: { - IDENT [12] { - name: x - } - IDENT [14] { - name: y - } + accu_var: @ac:0:0 + accu_init: { + LIST [19] { + elements: { } } - CALL [19] { - function: _+_ + } + loop_condition: { + CONSTANT [20] { value: true } + } + loop_step: { + CALL [21] { + function: _?_:_ args: { - IDENT [17] { - name: @result + CALL [22] { + function: _==_ + args: { + IDENT [23] { + name: @it:0:0 + } + IDENT [24] { + name: @it:1:0 + } + } } - LIST [18] { - elements: { - IDENT [11] { - name: x + CALL [25] { + function: _+_ + args: { + IDENT [26] { + name: @ac:0:0 + } + LIST [27] { + elements: { + IDENT [28] { + name: @it:0:0 + } + } } } } + IDENT [29] { + name: @ac:0:0 + } } } - IDENT [20] { - name: @result + } + result: { + IDENT [30] { + name: @ac:0:0 } } } } - result: { - IDENT [22] { - name: @result - } - } } } } } - } - } - result: { - IDENT [29] { - name: @result - } - } - } - LIST [32] { - elements: { - LIST [33] { - elements: { - CONSTANT [34] { value: 1 } + result: { + IDENT [31] { + name: @ac:1:0 + } } } - LIST [35] { + LIST [32] { elements: { - CONSTANT [36] { value: 2 } + LIST [33] { + elements: { + CONSTANT [34] { value: 1 } + } + } + LIST [35] { + elements: { + CONSTANT [36] { value: 2 } + } + } } } } @@ -2472,98 +2487,48 @@ CALL [1] { CONSTANT [6] { value: 3 } } } - LIST [7] { - elements: { - CONSTANT [8] { value: 2 } - CONSTANT [9] { value: 4 } - CONSTANT [10] { value: 6 } - } - } - } - } - CALL [11] { - function: _==_ - args: { - COMPREHENSION [12] { - iter_var: @it:1:0 - iter_var2: @it2:1:0 + COMPREHENSION [7] { + iter_var: @it:0:0 + iter_var2: @it2:0:0 iter_range: { - IDENT [13] { + IDENT [8] { name: @index0 } } - accu_var: @ac:1:0 + accu_var: @ac:0:0 accu_init: { - LIST [14] { + LIST [9] { elements: { } } } loop_condition: { - CONSTANT [15] { value: true } + CONSTANT [10] { value: true } } loop_step: { - CALL [16] { + CALL [11] { function: _+_ args: { - IDENT [17] { - name: @ac:1:0 - } - LIST [18] { + IDENT [12] { + name: @ac:0:0 + } + LIST [13] { elements: { - COMPREHENSION [19] { - iter_var: @it:0:0 - iter_var2: @it2:0:0 - iter_range: { - IDENT [20] { - name: @index0 - } - } - accu_var: @ac:0:0 - accu_init: { - LIST [21] { - elements: { - } - } - } - loop_condition: { - CONSTANT [22] { value: true } - } - loop_step: { - CALL [23] { + CALL [14] { + function: _+_ + args: { + CALL [15] { function: _+_ args: { - IDENT [24] { - name: @ac:0:0 + IDENT [16] { + name: @it:0:0 } - LIST [25] { - elements: { - CALL [26] { - function: _+_ - args: { - CALL [27] { - function: _+_ - args: { - IDENT [28] { - name: @it:0:0 - } - IDENT [29] { - name: @it2:0:0 - } - } - } - CONSTANT [30] { value: 1 } - } - } - } + IDENT [17] { + name: @it2:0:0 } } } - } - result: { - IDENT [31] { - name: @ac:0:0 - } + CONSTANT [18] { value: 1 } } } } @@ -2572,172 +2537,83 @@ CALL [1] { } } result: { - IDENT [32] { - name: @ac:1:0 + IDENT [19] { + name: @ac:0:0 } } } - LIST [33] { + LIST [20] { elements: { - IDENT [34] { - name: @index1 - } - IDENT [35] { - name: @index1 - } - IDENT [36] { - name: @index1 - } + CONSTANT [21] { value: 2 } + CONSTANT [22] { value: 4 } + CONSTANT [23] { value: 6 } } } } } - } -} -Test case: NESTED_MACROS_COMP_V2_2 -Source: [1, 2].transformList(i, y, [1, 2, 3].filter(x, x == y && i < y)) == [[1], [2]] -=====> -CALL [36] { - function: _==_ - args: { - COMPREHENSION [35] { - iter_var: i - iter_var2: y - iter_range: { - LIST [1] { - elements: { - CONSTANT [2] { value: 1 } - CONSTANT [3] { value: 2 } - } - } - } - accu_var: @result - accu_init: { - LIST [29] { - elements: { - } - } - } - loop_condition: { - CONSTANT [30] { value: true } - } - loop_step: { - CALL [33] { - function: _+_ - args: { - IDENT [31] { - name: @result + CALL [24] { + function: _==_ + args: { + COMPREHENSION [25] { + iter_var: @it:1:0 + iter_var2: @it2:1:0 + iter_range: { + IDENT [26] { + name: @index0 } - LIST [32] { + } + accu_var: @ac:1:0 + accu_init: { + LIST [27] { elements: { - COMPREHENSION [28] { - iter_var: x - iter_range: { - LIST [7] { - elements: { - CONSTANT [8] { value: 1 } - CONSTANT [9] { value: 2 } - CONSTANT [10] { value: 3 } - } - } - } - accu_var: @result - accu_init: { - LIST [20] { - elements: { - } - } - } - loop_condition: { - CONSTANT [21] { value: true } - } - loop_step: { - CALL [26] { - function: _?_:_ - args: { - CALL [16] { - function: _&&_ - args: { - CALL [14] { - function: _==_ - args: { - IDENT [13] { - name: x - } - IDENT [15] { - name: y - } - } - } - CALL [18] { - function: _<_ - args: { - IDENT [17] { - name: i - } - IDENT [19] { - name: y - } - } - } - } - } - CALL [24] { - function: _+_ - args: { - IDENT [22] { - name: @result - } - LIST [23] { - elements: { - IDENT [12] { - name: x - } - } - } - } - } - IDENT [25] { - name: @result - } - } - } - } - result: { - IDENT [27] { - name: @result + } + } + } + loop_condition: { + CONSTANT [28] { value: true } + } + loop_step: { + CALL [29] { + function: _+_ + args: { + IDENT [30] { + name: @ac:1:0 + } + LIST [31] { + elements: { + IDENT [32] { + name: @index1 } } } } } } - } - } - result: { - IDENT [34] { - name: @result - } - } - } - LIST [37] { - elements: { - LIST [38] { - elements: { - CONSTANT [39] { value: 1 } + result: { + IDENT [33] { + name: @ac:1:0 + } } } - LIST [40] { + LIST [34] { elements: { - CONSTANT [41] { value: 2 } + IDENT [35] { + name: @index2 + } + IDENT [36] { + name: @index2 + } + IDENT [37] { + name: @index2 + } } } } } } } -Test case: ADJACENT_NESTED_MACROS -Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +Test case: NESTED_MACROS_COMP_V2_2 +Source: [1, 2].transformList(i, y, [1, 2, 3].filter(x, x == y && i < y)) == [[1], [2]] =====> CALL [1] { function: cel.@block @@ -2751,74 +2627,112 @@ CALL [1] { CONSTANT [6] { value: 3 } } } - COMPREHENSION [7] { + } + } + CALL [7] { + function: _==_ + args: { + COMPREHENSION [8] { iter_var: @it:1:0 + iter_var2: @it2:1:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [9] { + elements: { + CONSTANT [10] { value: 1 } + CONSTANT [11] { value: 2 } + } } } accu_var: @ac:1:0 accu_init: { - LIST [9] { + LIST [12] { elements: { } } } loop_condition: { - CONSTANT [10] { value: true } + CONSTANT [13] { value: true } } loop_step: { - CALL [11] { + CALL [14] { function: _+_ args: { - IDENT [12] { + IDENT [15] { name: @ac:1:0 } - LIST [13] { + LIST [16] { elements: { - COMPREHENSION [14] { + COMPREHENSION [17] { iter_var: @it:0:0 iter_range: { - IDENT [15] { + IDENT [18] { name: @index0 } } accu_var: @ac:0:0 accu_init: { - LIST [16] { + LIST [19] { elements: { } } } loop_condition: { - CONSTANT [17] { value: true } + CONSTANT [20] { value: true } } loop_step: { - CALL [18] { - function: _+_ + CALL [21] { + function: _?_:_ args: { - IDENT [19] { - name: @ac:0:0 - } - LIST [20] { - elements: { - CALL [21] { - function: _+_ + CALL [22] { + function: _&&_ + args: { + CALL [23] { + function: _==_ + args: { + IDENT [24] { + name: @it:0:0 + } + IDENT [25] { + name: @it2:1:0 + } + } + } + CALL [26] { + function: _<_ args: { - IDENT [22] { + IDENT [27] { + name: @it:1:0 + } + IDENT [28] { + name: @it2:1:0 + } + } + } + } + } + CALL [29] { + function: _+_ + args: { + IDENT [30] { + name: @ac:0:0 + } + LIST [31] { + elements: { + IDENT [32] { name: @it:0:0 } - CONSTANT [23] { value: 1 } } } } } + IDENT [33] { + name: @ac:0:0 + } } } } result: { - IDENT [24] { + IDENT [34] { name: @ac:0:0 } } @@ -2829,28 +2743,31 @@ CALL [1] { } } result: { - IDENT [25] { + IDENT [35] { name: @ac:1:0 } } } - } - } - CALL [26] { - function: _==_ - args: { - IDENT [27] { - name: @index1 - } - IDENT [28] { - name: @index1 + LIST [36] { + elements: { + LIST [37] { + elements: { + CONSTANT [38] { value: 1 } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: 2 } + } + } + } } } } } } -Test case: ADJACENT_NESTED_MACROS_COMP_V2 -Source: [1,2,3].transformMap(i, x, [1, 2, 3].transformMap(i, x, i + x + 1)) == [1,2,3].transformMap(j, y, [1, 2, 3].transformMap(j, y, j + y + 1)) +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) =====> CALL [1] { function: cel.@block @@ -2865,17 +2782,17 @@ CALL [1] { } } COMPREHENSION [7] { - iter_var: @it:1:0 - iter_var2: @it2:1:0 + iter_var: @it:0:0 iter_range: { IDENT [8] { name: @index0 } } - accu_var: @ac:1:0 + accu_var: @ac:0:0 accu_init: { - MAP [9] { - + LIST [9] { + elements: { + } } } loop_condition: { @@ -2883,86 +2800,205 @@ CALL [1] { } loop_step: { CALL [11] { - function: cel.@mapInsert + function: _+_ args: { IDENT [12] { - name: @ac:1:0 + name: @ac:0:0 } - IDENT [13] { - name: @it:1:0 - } - COMPREHENSION [14] { - iter_var: @it:0:0 - iter_var2: @it2:0:0 - iter_range: { - IDENT [15] { - name: @index0 + LIST [13] { + elements: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @it:0:0 + } + CONSTANT [16] { value: 1 } + } } } - accu_var: @ac:0:0 - accu_init: { - MAP [16] { - + } + } + } + } + result: { + IDENT [17] { + name: @ac:0:0 + } + } + } + COMPREHENSION [18] { + iter_var: @it:1:0 + iter_range: { + IDENT [19] { + name: @index0 + } + } + accu_var: @ac:1:0 + accu_init: { + LIST [20] { + elements: { + } + } + } + loop_condition: { + CONSTANT [21] { value: true } + } + loop_step: { + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @ac:1:0 + } + LIST [24] { + elements: { + IDENT [25] { + name: @index1 } } - loop_condition: { - CONSTANT [17] { value: true } - } - loop_step: { - CALL [18] { - function: cel.@mapInsert + } + } + } + } + result: { + IDENT [26] { + name: @ac:1:0 + } + } + } + } + } + CALL [27] { + function: _==_ + args: { + IDENT [28] { + name: @index2 + } + IDENT [29] { + name: @index2 + } + } + } + } +} +Test case: ADJACENT_NESTED_MACROS_COMP_V2 +Source: [1,2,3].transformMap(i, x, [1, 2, 3].transformMap(i, x, i + x + 1)) == [1,2,3].transformMap(j, y, [1, 2, 3].transformMap(j, y, j + y + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + COMPREHENSION [7] { + iter_var: @it:0:0 + iter_var2: @it2:0:0 + iter_range: { + IDENT [8] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + MAP [9] { + + } + } + loop_condition: { + CONSTANT [10] { value: true } + } + loop_step: { + CALL [11] { + function: cel.@mapInsert + args: { + IDENT [12] { + name: @ac:0:0 + } + IDENT [13] { + name: @it:0:0 + } + CALL [14] { + function: _+_ + args: { + CALL [15] { + function: _+_ args: { - IDENT [19] { - name: @ac:0:0 - } - IDENT [20] { + IDENT [16] { name: @it:0:0 } - CALL [21] { - function: _+_ - args: { - CALL [22] { - function: _+_ - args: { - IDENT [23] { - name: @it:0:0 - } - IDENT [24] { - name: @it2:0:0 - } - } - } - CONSTANT [25] { value: 1 } - } + IDENT [17] { + name: @it2:0:0 } } } - } - result: { - IDENT [26] { - name: @ac:0:0 - } + CONSTANT [18] { value: 1 } } } } } } result: { - IDENT [27] { + IDENT [19] { + name: @ac:0:0 + } + } + } + COMPREHENSION [20] { + iter_var: @it:1:0 + iter_var2: @it2:1:0 + iter_range: { + IDENT [21] { + name: @index0 + } + } + accu_var: @ac:1:0 + accu_init: { + MAP [22] { + + } + } + loop_condition: { + CONSTANT [23] { value: true } + } + loop_step: { + CALL [24] { + function: cel.@mapInsert + args: { + IDENT [25] { + name: @ac:1:0 + } + IDENT [26] { + name: @it:1:0 + } + IDENT [27] { + name: @index1 + } + } + } + } + result: { + IDENT [28] { name: @ac:1:0 } } } } } - CALL [28] { + CALL [29] { function: _==_ args: { - IDENT [29] { - name: @index1 - } IDENT [30] { - name: @index1 + name: @index2 + } + IDENT [31] { + name: @index2 } } } @@ -3118,86 +3154,89 @@ CALL [1] { CONSTANT [8] { value: 4 } } } - LIST [9] { - elements: { + COMPREHENSION [9] { + iter_var: @it:0:0 + iter_range: { IDENT [10] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [11] { + elements: { + } + } + } + loop_condition: { + CONSTANT [12] { value: true } + } + loop_step: { + CALL [13] { + function: _+_ + args: { + IDENT [14] { + name: @ac:0:0 + } + LIST [15] { + elements: { + IDENT [16] { + name: @index1 + } + } + } + } + } + } + result: { + IDENT [17] { + name: @ac:0:0 + } + } + } + LIST [18] { + elements: { + IDENT [19] { name: @index1 } - IDENT [11] { + IDENT [20] { name: @index1 } } } } } - CALL [12] { + CALL [21] { function: _==_ args: { - COMPREHENSION [13] { + COMPREHENSION [22] { iter_var: @it:1:0 iter_range: { - IDENT [14] { + IDENT [23] { name: @index0 } } accu_var: @ac:1:0 accu_init: { - LIST [15] { + LIST [24] { elements: { } } } loop_condition: { - CONSTANT [16] { value: true } + CONSTANT [25] { value: true } } loop_step: { - CALL [17] { + CALL [26] { function: _+_ args: { - IDENT [18] { + IDENT [27] { name: @ac:1:0 } - LIST [19] { + LIST [28] { elements: { - COMPREHENSION [20] { - iter_var: @it:0:0 - iter_range: { - IDENT [21] { - name: @index0 - } - } - accu_var: @ac:0:0 - accu_init: { - LIST [22] { - elements: { - } - } - } - loop_condition: { - CONSTANT [23] { value: true } - } - loop_step: { - CALL [24] { - function: _+_ - args: { - IDENT [25] { - name: @ac:0:0 - } - LIST [26] { - elements: { - IDENT [27] { - name: @index1 - } - } - } - } - } - } - result: { - IDENT [28] { - name: @ac:0:0 - } - } + IDENT [29] { + name: @index2 } } } @@ -3205,18 +3244,18 @@ CALL [1] { } } result: { - IDENT [29] { + IDENT [30] { name: @ac:1:0 } } } - LIST [30] { + LIST [31] { elements: { - IDENT [31] { - name: @index2 - } IDENT [32] { - name: @index2 + name: @index3 + } + IDENT [33] { + name: @index3 } } } @@ -3244,88 +3283,91 @@ CALL [1] { CONSTANT [8] { value: 4 } } } - LIST [9] { - elements: { + COMPREHENSION [9] { + iter_var: @it:0:0 + iter_var2: @it2:0:0 + iter_range: { IDENT [10] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [11] { + elements: { + } + } + } + loop_condition: { + CONSTANT [12] { value: true } + } + loop_step: { + CALL [13] { + function: _+_ + args: { + IDENT [14] { + name: @ac:0:0 + } + LIST [15] { + elements: { + IDENT [16] { + name: @index1 + } + } + } + } + } + } + result: { + IDENT [17] { + name: @ac:0:0 + } + } + } + LIST [18] { + elements: { + IDENT [19] { name: @index1 } - IDENT [11] { + IDENT [20] { name: @index1 } } } } } - CALL [12] { + CALL [21] { function: _==_ args: { - COMPREHENSION [13] { + COMPREHENSION [22] { iter_var: @it:1:0 iter_var2: @it2:1:0 iter_range: { - IDENT [14] { + IDENT [23] { name: @index0 } } accu_var: @ac:1:0 accu_init: { - LIST [15] { + LIST [24] { elements: { } } } loop_condition: { - CONSTANT [16] { value: true } + CONSTANT [25] { value: true } } loop_step: { - CALL [17] { + CALL [26] { function: _+_ args: { - IDENT [18] { + IDENT [27] { name: @ac:1:0 } - LIST [19] { + LIST [28] { elements: { - COMPREHENSION [20] { - iter_var: @it:0:0 - iter_var2: @it2:0:0 - iter_range: { - IDENT [21] { - name: @index0 - } - } - accu_var: @ac:0:0 - accu_init: { - LIST [22] { - elements: { - } - } - } - loop_condition: { - CONSTANT [23] { value: true } - } - loop_step: { - CALL [24] { - function: _+_ - args: { - IDENT [25] { - name: @ac:0:0 - } - LIST [26] { - elements: { - IDENT [27] { - name: @index1 - } - } - } - } - } - } - result: { - IDENT [28] { - name: @ac:0:0 - } - } + IDENT [29] { + name: @index2 } } } @@ -3333,18 +3375,18 @@ CALL [1] { } } result: { - IDENT [29] { + IDENT [30] { name: @ac:1:0 } } } - LIST [30] { + LIST [31] { elements: { - IDENT [31] { - name: @index2 - } IDENT [32] { - name: @index2 + name: @index3 + } + IDENT [33] { + name: @index3 } } } @@ -4755,4 +4797,1135 @@ CALL [1] { } } } +} +Test case: VALUE_NUMBERING_COMMUTATIVE_ADD_CONVERSE_RELATION_LOGICAL_AND +Source: (msg.single_int64 + msg.single_int32 > 5 && msg.oneof_type.payload.single_int64 < msg.single_int64 + msg.single_int32) == (msg.single_int32 + msg.single_int64 > msg.oneof_type.payload.single_int64 && 5 < msg.single_int32 + msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _+_ + args: { + SELECT [4] { + IDENT [5] { + name: msg + }.single_int64 + } + SELECT [6] { + IDENT [7] { + name: msg + }.single_int32 + } + } + } + CALL [8] { + function: _&&_ + args: { + CALL [9] { + function: _>_ + args: { + IDENT [10] { + name: @index0 + } + CONSTANT [11] { value: 5 } + } + } + CALL [12] { + function: _<_ + args: { + SELECT [13] { + SELECT [14] { + SELECT [15] { + IDENT [16] { + name: msg + }.oneof_type + }.payload + }.single_int64 + } + IDENT [17] { + name: @index0 + } + } + } + } + } + } + } + CALL [18] { + function: _==_ + args: { + IDENT [19] { + name: @index1 + } + IDENT [20] { + name: @index1 + } + } + } + } +} +Test case: VALUE_NUMBERING_COMMUTATIVE_MULTIPLY_EQUALITY_LOGICAL_OR +Source: (msg.oneof_type.payload.single_int32 * msg.single_int64 == 24 || msg.single_int32 != msg.oneof_type.payload.single_int64) && (msg.oneof_type.payload.single_int64 != msg.single_int32 || 24 == msg.single_int64 * msg.oneof_type.payload.single_int32) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + CALL [6] { + function: _||_ + args: { + CALL [7] { + function: _==_ + args: { + CALL [8] { + function: _*_ + args: { + SELECT [9] { + IDENT [10] { + name: @index0 + }.single_int32 + } + SELECT [11] { + IDENT [12] { + name: msg + }.single_int64 + } + } + } + CONSTANT [13] { value: 24 } + } + } + CALL [14] { + function: _!=_ + args: { + SELECT [15] { + IDENT [16] { + name: msg + }.single_int32 + } + SELECT [17] { + IDENT [18] { + name: @index0 + }.single_int64 + } + } + } + } + } + } + } + CALL [19] { + function: _&&_ + args: { + IDENT [20] { + name: @index1 + } + IDENT [21] { + name: @index1 + } + } + } + } +} +Test case: HOIST_NESTED_COMPREHENSION +Source: msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == 2)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + SELECT [4] { + IDENT [5] { + name: msg + }.repeated_int32 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _==_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 2 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + } + } + COMPREHENSION [16] { + iter_var: @it:1:0 + iter_range: { + SELECT [17] { + IDENT [18] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:1:0 + accu_init: { + CONSTANT [19] { value: true } + } + loop_condition: { + CALL [20] { + function: @not_strictly_false + args: { + IDENT [21] { + name: @ac:1:0 + } + } + } + } + loop_step: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @ac:1:0 + } + IDENT [24] { + name: @index0 + } + } + } + } + result: { + IDENT [25] { + name: @ac:1:0 + } + } + } + } +} +Test case: HOIST_INVARIANT_ARITHMETIC +Source: msg.repeated_int64.exists(i, i == msg.single_int64 * 2 + msg.single_int32) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _+_ + args: { + CALL [4] { + function: _*_ + args: { + SELECT [5] { + IDENT [6] { + name: msg + }.single_int64 + } + CONSTANT [7] { value: 2 } + } + } + SELECT [8] { + IDENT [9] { + name: msg + }.single_int32 + } + } + } + } + } + COMPREHENSION [10] { + iter_var: @it:0:0 + iter_range: { + SELECT [11] { + IDENT [12] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [13] { value: false } + } + loop_condition: { + CALL [14] { + function: @not_strictly_false + args: { + CALL [15] { + function: !_ + args: { + IDENT [16] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [17] { + function: _||_ + args: { + IDENT [18] { + name: @ac:0:0 + } + CALL [19] { + function: _==_ + args: { + IDENT [20] { + name: @it:0:0 + } + IDENT [21] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [22] { + name: @ac:0:0 + } + } + } + } +} +Test case: HOIST_ZERO_TRIP_ERROR_NOT_EVALUATED +Source: msg.repeated_nested_message.exists(m, m.bb == 1 / (msg.single_int32 - 5)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _/_ + args: { + CONSTANT [4] { value: 1 } + CALL [5] { + function: _-_ + args: { + SELECT [6] { + IDENT [7] { + name: msg + }.single_int32 + } + CONSTANT [8] { value: 5 } + } + } + } + } + } + } + COMPREHENSION [9] { + iter_var: @it:0:0 + iter_range: { + SELECT [10] { + IDENT [11] { + name: msg + }.repeated_nested_message + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [12] { value: false } + } + loop_condition: { + CALL [13] { + function: @not_strictly_false + args: { + CALL [14] { + function: !_ + args: { + IDENT [15] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _==_ + args: { + SELECT [19] { + IDENT [20] { + name: @it:0:0 + }.bb + } + IDENT [21] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [22] { + name: @ac:0:0 + } + } + } + } +} +Test case: HOIST_MAP_ACCUMULATION_PRESERVED +Source: msg.repeated_int64.map(i, msg.single_int64 * 2) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _*_ + args: { + SELECT [4] { + IDENT [5] { + name: msg + }.single_int64 + } + CONSTANT [6] { value: 2 } + } + } + } + } + COMPREHENSION [7] { + iter_var: @it:0:0 + iter_range: { + SELECT [8] { + IDENT [9] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [10] { + elements: { + } + } + } + loop_condition: { + CONSTANT [11] { value: true } + } + loop_step: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @ac:0:0 + } + LIST [14] { + elements: { + IDENT [15] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [16] { + name: @ac:0:0 + } + } + } + } +} +Test case: HOIST_LIST_LITERAL +Source: msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + SELECT [4] { + IDENT [5] { + name: msg + }.single_int64 + } + SELECT [6] { + IDENT [7] { + name: msg + }.single_int32 + } + } + } + } + } + COMPREHENSION [8] { + iter_var: @it:0:0 + iter_range: { + SELECT [9] { + IDENT [10] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [11] { value: false } + } + loop_condition: { + CALL [12] { + function: @not_strictly_false + args: { + CALL [13] { + function: !_ + args: { + IDENT [14] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [15] { + function: _||_ + args: { + IDENT [16] { + name: @ac:0:0 + } + CALL [17] { + function: @in + args: { + IDENT [18] { + name: @it:0:0 + } + IDENT [19] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [20] { + name: @ac:0:0 + } + } + } + } +} +Test case: HOIST_LIST_APPENDED_TO_ITER_VAR +Source: [[1], [2]].map(l, l + [msg.single_int64]) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + SELECT [4] { + IDENT [5] { + name: msg + }.single_int64 + } + } + } + } + } + COMPREHENSION [6] { + iter_var: @it:0:0 + iter_range: { + LIST [7] { + elements: { + LIST [8] { + elements: { + CONSTANT [9] { value: 1 } + } + } + LIST [10] { + elements: { + CONSTANT [11] { value: 2 } + } + } + } + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [12] { + elements: { + } + } + } + loop_condition: { + CONSTANT [13] { value: true } + } + loop_step: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @ac:0:0 + } + LIST [16] { + elements: { + CALL [17] { + function: _+_ + args: { + IDENT [18] { + name: @it:0:0 + } + IDENT [19] { + name: @index0 + } + } + } + } + } + } + } + } + result: { + IDENT [20] { + name: @ac:0:0 + } + } + } + } +} +Test case: HOIST_INVARIANT_INSIDE_DUPLICATE +Source: msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) || msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + SELECT [4] { + IDENT [5] { + name: msg + }.single_int64 + } + SELECT [6] { + IDENT [7] { + name: msg + }.single_int32 + } + } + } + COMPREHENSION [8] { + iter_var: @it:0:0 + iter_range: { + SELECT [9] { + IDENT [10] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [11] { value: false } + } + loop_condition: { + CALL [12] { + function: @not_strictly_false + args: { + CALL [13] { + function: !_ + args: { + IDENT [14] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [15] { + function: _||_ + args: { + IDENT [16] { + name: @ac:0:0 + } + CALL [17] { + function: @in + args: { + IDENT [18] { + name: @it:0:0 + } + IDENT [19] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [20] { + name: @ac:0:0 + } + } + } + } + } + CALL [21] { + function: _||_ + args: { + IDENT [22] { + name: @index1 + } + IDENT [23] { + name: @index1 + } + } + } + } +} +Test case: HOIST_INVARIANT_OF_NESTED_COMPREHENSION +Source: msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == msg.single_int64 * 2)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _*_ + args: { + SELECT [4] { + IDENT [5] { + name: msg + }.single_int64 + } + CONSTANT [6] { value: 2 } + } + } + COMPREHENSION [7] { + iter_var: @it:0:0 + iter_range: { + SELECT [8] { + IDENT [9] { + name: msg + }.repeated_int32 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [10] { value: false } + } + loop_condition: { + CALL [11] { + function: @not_strictly_false + args: { + CALL [12] { + function: !_ + args: { + IDENT [13] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [14] { + function: _||_ + args: { + IDENT [15] { + name: @ac:0:0 + } + CALL [16] { + function: _==_ + args: { + IDENT [17] { + name: @it:0:0 + } + IDENT [18] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [19] { + name: @ac:0:0 + } + } + } + } + } + COMPREHENSION [20] { + iter_var: @it:1:0 + iter_range: { + SELECT [21] { + IDENT [22] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:1:0 + accu_init: { + CONSTANT [23] { value: true } + } + loop_condition: { + CALL [24] { + function: @not_strictly_false + args: { + IDENT [25] { + name: @ac:1:0 + } + } + } + } + loop_step: { + CALL [26] { + function: _&&_ + args: { + IDENT [27] { + name: @ac:1:0 + } + IDENT [28] { + name: @index1 + } + } + } + } + result: { + IDENT [29] { + name: @ac:1:0 + } + } + } + } +} +Test case: HOIST_SHARED_TERMS_ONCE +Source: msg.repeated_int64.exists(i, i == msg.single_int64 + msg.single_int32 + msg.single_sint64) && [msg.single_int64, msg.single_int32, msg.single_sint64].size() > 0 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.single_int64 + } + SELECT [5] { + IDENT [6] { + name: msg + }.single_int32 + } + SELECT [7] { + IDENT [8] { + name: msg + }.single_sint64 + } + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + IDENT [11] { + name: @index0 + } + IDENT [12] { + name: @index1 + } + } + } + IDENT [13] { + name: @index2 + } + } + } + } + } + CALL [14] { + function: _&&_ + args: { + COMPREHENSION [15] { + iter_var: @it:0:0 + iter_range: { + SELECT [16] { + IDENT [17] { + name: msg + }.repeated_int64 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [18] { value: false } + } + loop_condition: { + CALL [19] { + function: @not_strictly_false + args: { + CALL [20] { + function: !_ + args: { + IDENT [21] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [22] { + function: _||_ + args: { + IDENT [23] { + name: @ac:0:0 + } + CALL [24] { + function: _==_ + args: { + IDENT [25] { + name: @it:0:0 + } + IDENT [26] { + name: @index3 + } + } + } + } + } + } + result: { + IDENT [27] { + name: @ac:0:0 + } + } + } + CALL [28] { + function: _>_ + args: { + CALL [29] { + function: size + target: { + LIST [30] { + elements: { + IDENT [31] { + name: @index0 + } + IDENT [32] { + name: @index1 + } + IDENT [33] { + name: @index2 + } + } + } + } + args: { + } + } + CONSTANT [34] { value: 0 } + } + } + } + } + } +} +Test case: HOIST_SHARED_WITH_ACCUMULATED_LIST +Source: msg.repeated_int64.exists(i, i in [msg.single_int64]) && msg.repeated_int64.map(i, msg.single_int64).size() > 0 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.single_int64 + } + LIST [5] { + elements: { + IDENT [6] { + name: @index0 + } + } + } + SELECT [7] { + IDENT [8] { + name: msg + }.repeated_int64 + } + } + } + CALL [9] { + function: _&&_ + args: { + COMPREHENSION [10] { + iter_var: @it:0:0 + iter_range: { + IDENT [11] { + name: @index2 + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [12] { value: false } + } + loop_condition: { + CALL [13] { + function: @not_strictly_false + args: { + CALL [14] { + function: !_ + args: { + IDENT [15] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: @in + args: { + IDENT [19] { + name: @it:0:0 + } + IDENT [20] { + name: @index1 + } + } + } + } + } + } + result: { + IDENT [21] { + name: @ac:0:0 + } + } + } + CALL [22] { + function: _>_ + args: { + CALL [23] { + function: size + target: { + COMPREHENSION [24] { + iter_var: @it:0:1 + iter_range: { + IDENT [25] { + name: @index2 + } + } + accu_var: @ac:0:1 + accu_init: { + LIST [26] { + elements: { + } + } + } + loop_condition: { + CONSTANT [27] { value: true } + } + loop_step: { + CALL [28] { + function: _+_ + args: { + IDENT [29] { + name: @ac:0:1 + } + LIST [30] { + elements: { + IDENT [31] { + name: @index0 + } + } + } + } + } + } + result: { + IDENT [32] { + name: @ac:0:1 + } + } + } + } + args: { + } + } + CONSTANT [33] { value: 0 } + } + } + } + } + } } \ No newline at end of file diff --git a/optimizer/src/test/resources/subexpression_unparsed.baseline b/optimizer/src/test/resources/subexpression_unparsed.baseline index 411d74828..02dac5ed3 100644 --- a/optimizer/src/test/resources/subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/subexpression_unparsed.baseline @@ -134,13 +134,13 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [[2, 3, 4], [2, 3, 4], [2, 3, 4]] =====> Result: true -Unparsed: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@it:1:0, @index0.map(@it:0:0, @it:0:0 + 1)) == [@index1, @index1, @index1]) +Unparsed: cel.@block([[1, 2, 3], @index0.map(@it:0:0, @it:0:0 + 1), [2, 3, 4]], @index0.map(@it:1:0, @index1) == [@index2, @index2, @index2]) Test case: NESTED_MACROS_2 Source: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] =====> Result: true -Unparsed: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] +Unparsed: cel.@block([[1, 2, 3]], [1, 2].map(@it:1:0, @index0.filter(@it:0:0, @it:0:0 == @it:1:0)) == [[1], [2]]) Test case: NESTED_MACROS_3 Source: [1,2,3].map(i, i * 2) + [1,2,3].map(i, i * 2).map(i, i * 2) @@ -152,25 +152,25 @@ Test case: NESTED_MACROS_COMP_V2_1 Source: [1,2,3].transformList(i, v, [1, 2, 3].transformList(i, v, i + v + 1)) == [[2, 4, 6], [2, 4, 6], [2, 4, 6]] =====> Result: true -Unparsed: cel.@block([[1, 2, 3], [2, 4, 6]], @index0.transformList(@it:1:0, @it2:1:0, @index0.transformList(@it:0:0, @it2:0:0, @it:0:0 + @it2:0:0 + 1)) == [@index1, @index1, @index1]) +Unparsed: cel.@block([[1, 2, 3], @index0.transformList(@it:0:0, @it2:0:0, @it:0:0 + @it2:0:0 + 1), [2, 4, 6]], @index0.transformList(@it:1:0, @it2:1:0, @index1) == [@index2, @index2, @index2]) Test case: NESTED_MACROS_COMP_V2_2 Source: [1, 2].transformList(i, y, [1, 2, 3].filter(x, x == y && i < y)) == [[1], [2]] =====> Result: true -Unparsed: [1, 2].transformList(i, y, [1, 2, 3].filter(x, x == y && i < y)) == [[1], [2]] +Unparsed: cel.@block([[1, 2, 3]], [1, 2].transformList(@it:1:0, @it2:1:0, @index0.filter(@it:0:0, @it:0:0 == @it2:1:0 && @it:1:0 < @it2:1:0)) == [[1], [2]]) Test case: ADJACENT_NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) =====> Result: true -Unparsed: cel.@block([[1, 2, 3], @index0.map(@it:1:0, @index0.map(@it:0:0, @it:0:0 + 1))], @index1 == @index1) +Unparsed: cel.@block([[1, 2, 3], @index0.map(@it:0:0, @it:0:0 + 1), @index0.map(@it:1:0, @index1)], @index2 == @index2) Test case: ADJACENT_NESTED_MACROS_COMP_V2 Source: [1,2,3].transformMap(i, x, [1, 2, 3].transformMap(i, x, i + x + 1)) == [1,2,3].transformMap(j, y, [1, 2, 3].transformMap(j, y, j + y + 1)) =====> Result: true -Unparsed: cel.@block([[1, 2, 3], @index0.transformMap(@it:1:0, @it2:1:0, @index0.transformMap(@it:0:0, @it2:0:0, @it:0:0 + @it2:0:0 + 1))], @index1 == @index1) +Unparsed: cel.@block([[1, 2, 3], @index0.transformMap(@it:0:0, @it2:0:0, @it:0:0 + @it2:0:0 + 1), @index0.transformMap(@it:1:0, @it2:1:0, @index1)], @index2 == @index2) Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] @@ -188,13 +188,13 @@ Test case: MACRO_ITER_VAR_NOT_REFERENCED Source: [1,2].map(i, [1, 2].map(i, [3,4])) == [[[3, 4], [3, 4]], [[3, 4], [3, 4]]] =====> Result: true -Unparsed: cel.@block([[1, 2], [3, 4], [@index1, @index1]], @index0.map(@it:1:0, @index0.map(@it:0:0, @index1)) == [@index2, @index2]) +Unparsed: cel.@block([[1, 2], [3, 4], @index0.map(@it:0:0, @index1), [@index1, @index1]], @index0.map(@it:1:0, @index2) == [@index3, @index3]) Test case: MACRO_ITER_VAR2_NOT_REFERENCED Source: [1,2].transformList(i, v, [1, 2].transformList(i, v, [3,4])) == [[[3, 4], [3, 4]], [[3, 4], [3, 4]]] =====> Result: true -Unparsed: cel.@block([[1, 2], [3, 4], [@index1, @index1]], @index0.transformList(@it:1:0, @it2:1:0, @index0.transformList(@it:0:0, @it2:0:0, @index1)) == [@index2, @index2]) +Unparsed: cel.@block([[1, 2], [3, 4], @index0.transformList(@it:0:0, @it2:0:0, @index1), [@index1, @index1]], @index0.transformList(@it:1:0, @it2:1:0, @index2) == [@index3, @index3]) Test case: MACRO_SHADOWED_VARIABLE Source: [x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3 @@ -314,4 +314,76 @@ Test case: CUSTOM_FUNCTION_ELIMINABLE Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) =====> Result: 31 -Unparsed: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) \ No newline at end of file +Unparsed: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) + +Test case: VALUE_NUMBERING_COMMUTATIVE_ADD_CONVERSE_RELATION_LOGICAL_AND +Source: (msg.single_int64 + msg.single_int32 > 5 && msg.oneof_type.payload.single_int64 < msg.single_int64 + msg.single_int32) == (msg.single_int32 + msg.single_int64 > msg.oneof_type.payload.single_int64 && 5 < msg.single_int32 + msg.single_int64) +=====> +Result: true +Unparsed: cel.@block([msg.single_int64 + msg.single_int32, @index0 > 5 && msg.oneof_type.payload.single_int64 < @index0], @index1 == @index1) + +Test case: VALUE_NUMBERING_COMMUTATIVE_MULTIPLY_EQUALITY_LOGICAL_OR +Source: (msg.oneof_type.payload.single_int32 * msg.single_int64 == 24 || msg.single_int32 != msg.oneof_type.payload.single_int64) && (msg.oneof_type.payload.single_int64 != msg.single_int32 || 24 == msg.single_int64 * msg.oneof_type.payload.single_int32) +=====> +Result: true +Unparsed: cel.@block([msg.oneof_type.payload, @index0.single_int32 * msg.single_int64 == 24 || msg.single_int32 != @index0.single_int64], @index1 && @index1) + +Test case: HOIST_NESTED_COMPREHENSION +Source: msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == 2)) +=====> +Result: true +Unparsed: cel.@block([msg.repeated_int32.exists(@it:0:0, @it:0:0 == 2)], msg.repeated_int64.all(@it:1:0, @index0)) + +Test case: HOIST_INVARIANT_ARITHMETIC +Source: msg.repeated_int64.exists(i, i == msg.single_int64 * 2 + msg.single_int32) +=====> +Result: false +Unparsed: cel.@block([msg.single_int64 * 2 + msg.single_int32], msg.repeated_int64.exists(@it:0:0, @it:0:0 == @index0)) + +Test case: HOIST_ZERO_TRIP_ERROR_NOT_EVALUATED +Source: msg.repeated_nested_message.exists(m, m.bb == 1 / (msg.single_int32 - 5)) +=====> +Result: false +Unparsed: cel.@block([1 / (msg.single_int32 - 5)], msg.repeated_nested_message.exists(@it:0:0, @it:0:0.bb == @index0)) + +Test case: HOIST_MAP_ACCUMULATION_PRESERVED +Source: msg.repeated_int64.map(i, msg.single_int64 * 2) +=====> +Result: [6, 6, 6] +Unparsed: cel.@block([msg.single_int64 * 2], msg.repeated_int64.map(@it:0:0, @index0)) + +Test case: HOIST_LIST_LITERAL +Source: msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) +=====> +Result: true +Unparsed: cel.@block([[msg.single_int64, msg.single_int32]], msg.repeated_int64.exists(@it:0:0, @it:0:0 in @index0)) + +Test case: HOIST_LIST_APPENDED_TO_ITER_VAR +Source: [[1], [2]].map(l, l + [msg.single_int64]) +=====> +Result: [[1, 3], [2, 3]] +Unparsed: cel.@block([[msg.single_int64]], [[1], [2]].map(@it:0:0, @it:0:0 + @index0)) + +Test case: HOIST_INVARIANT_INSIDE_DUPLICATE +Source: msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) || msg.repeated_int64.exists(i, i in [msg.single_int64, msg.single_int32]) +=====> +Result: true +Unparsed: cel.@block([[msg.single_int64, msg.single_int32], msg.repeated_int64.exists(@it:0:0, @it:0:0 in @index0)], @index1 || @index1) + +Test case: HOIST_INVARIANT_OF_NESTED_COMPREHENSION +Source: msg.repeated_int64.all(i, msg.repeated_int32.exists(j, j == msg.single_int64 * 2)) +=====> +Result: false +Unparsed: cel.@block([msg.single_int64 * 2, msg.repeated_int32.exists(@it:0:0, @it:0:0 == @index0)], msg.repeated_int64.all(@it:1:0, @index1)) + +Test case: HOIST_SHARED_TERMS_ONCE +Source: msg.repeated_int64.exists(i, i == msg.single_int64 + msg.single_int32 + msg.single_sint64) && [msg.single_int64, msg.single_int32, msg.single_sint64].size() > 0 +=====> +Result: false +Unparsed: cel.@block([msg.single_int64, msg.single_int32, msg.single_sint64, @index0 + @index1 + @index2], msg.repeated_int64.exists(@it:0:0, @it:0:0 == @index3) && [@index0, @index1, @index2].size() > 0) + +Test case: HOIST_SHARED_WITH_ACCUMULATED_LIST +Source: msg.repeated_int64.exists(i, i in [msg.single_int64]) && msg.repeated_int64.map(i, msg.single_int64).size() > 0 +=====> +Result: true +Unparsed: cel.@block([msg.single_int64, [@index0], msg.repeated_int64], @index2.exists(@it:0:0, @it:0:0 in @index1) && @index2.map(@it:0:1, @index0).size() > 0) \ No newline at end of file diff --git a/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java index 3fe2e3322..0315c7c02 100644 --- a/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java +++ b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java @@ -78,12 +78,12 @@ enum TestYamlPolicy { REQUIRED_LABELS( "required_labels", true, - "cel.@block([spec.labels.filter(@it:0:0, !(@it:0:0 in resource.labels)), spec.labels," - + " resource.labels.transformList(@it:0:1, @it2:0:1, @it:0:1 in @index1 && @it2:0:1 !=" - + " @index1[@it:0:1], @it:0:1)], (@index0.size() > 0) ? optional.of(\"missing one or" - + " more required labels: [\"\" + @index0.join(\"\", \"\") + \"\"]\") :" - + " ((@index2.size() > 0) ? optional.of(\"invalid values provided on one or more" - + " labels: [\"\" + @index2.join(\"\", \"\") + \"\"]\") : optional.none()))"), + "cel.@block([resource.labels, spec.labels.filter(@it:0:0, !(@it:0:0 in @index0))," + + " spec.labels, @index0.transformList(@it:0:1, @it2:0:1, @it:0:1 in @index2 &&" + + " @it2:0:1 != @index2[@it:0:1], @it:0:1)], (@index1.size() > 0) ?" + + " optional.of(\"missing one or more required labels: [\"\" + @index1.join(\"\", \"\")" + + " + \"\"]\") : ((@index3.size() > 0) ? optional.of(\"invalid values provided on one" + + " or more labels: [\"\" + @index3.join(\"\", \"\") + \"\"]\") : optional.none()))"), RESTRICTED_DESTINATIONS( "restricted_destinations", false, @@ -96,9 +96,9 @@ enum TestYamlPolicy { K8S( "k8s", true, - "cel.@block([resource.labels.?environment.orValue(\"prod\")]," + "cel.@block([resource.labels.?environment.orValue(\"prod\"), @index0 + \".\"]," + " !(resource.labels.?break_glass.orValue(\"false\") == \"true\" ||" - + " resource.containers.all(@it:0:0, @it:0:0.startsWith(@index0 + \".\"))) ?" + + " resource.containers.all(@it:0:0, @it:0:0.startsWith(@index1))) ?" + " optional.of(\"only \" + @index0 + \" containers are allowed in namespace \" +" + " resource.namespace) : optional.none())"), PB(