Permutations!
This commit is contained in:
parent
45a3710626
commit
946d4b96b1
11
examples/permutations.mq
Normal file
11
examples/permutations.mq
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
var factorial = [n | if (n < 2) [1] [factorial (n-1) * n]];
|
||||||
|
|
||||||
|
var for_all_permutations = [array fun |
|
||||||
|
var iter = [start stop x | if (start >= stop) [x] [iter (start+1) stop (fun x)]];
|
||||||
|
iter 0 (factorial (len array)) array
|
||||||
|
];
|
||||||
|
|
||||||
|
for_all_permutations (flat 1 2 3 4 5) [array|
|
||||||
|
say array;
|
||||||
|
permute array
|
||||||
|
];
|
@ -362,6 +362,29 @@ Interpreter::Interpreter()
|
|||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
global.force_define("permute", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
||||||
|
Array array;
|
||||||
|
for (auto &arg : args) {
|
||||||
|
switch (arg.type) {
|
||||||
|
case Value::Type::Array:
|
||||||
|
std::move(arg.array.elements.begin(), arg.array.elements.end(), std::back_inserter(array.elements));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Value::Type::Block:
|
||||||
|
for (auto j = 0u; j < arg.blk.size(); ++j) {
|
||||||
|
array.elements.push_back(Try(arg.blk.index(i, j)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
array.elements.push_back(std::move(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::next_permutation(array.elements.begin(), array.elements.end());
|
||||||
|
return Value::from(std::move(array));
|
||||||
|
});
|
||||||
|
|
||||||
global.force_define("chord", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
global.force_define("chord", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
||||||
Chord chord;
|
Chord chord;
|
||||||
Try(create_chord(chord.notes, i, std::move(args)));
|
Try(create_chord(chord.notes, i, std::move(args)));
|
||||||
|
@ -89,7 +89,7 @@ struct Runner
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Run given source
|
/// Run given source
|
||||||
Result<void> run(std::string_view source, std::string_view filename)
|
Result<void> run(std::string_view source, std::string_view filename, bool output = false)
|
||||||
{
|
{
|
||||||
auto ast = Try(Parser::parse(source, filename));
|
auto ast = Try(Parser::parse(source, filename));
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ struct Runner
|
|||||||
dump(ast);
|
dump(ast);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (auto result = Try(interpreter.eval(std::move(ast))); result.type != Value::Type::Nil) {
|
if (auto result = Try(interpreter.eval(std::move(ast))); output && result.type != Value::Type::Nil) {
|
||||||
std::cout << result << std::endl;
|
std::cout << result << std::endl;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -185,6 +185,7 @@ static Result<void> Main(std::span<char const*> args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (runnables.empty() || enable_repl) {
|
if (runnables.empty() || enable_repl) {
|
||||||
|
enable_repl = true;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *input_buffer = readline("> ");
|
char *input_buffer = readline("> ");
|
||||||
if (input_buffer == nullptr) {
|
if (input_buffer == nullptr) {
|
||||||
@ -215,7 +216,7 @@ static Result<void> Main(std::span<char const*> args)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = runner.run(raw, "<repl>");
|
auto result = runner.run(raw, "<repl>", true);
|
||||||
if (not result.has_value()) {
|
if (not result.has_value()) {
|
||||||
std::cout << std::flush;
|
std::cout << std::flush;
|
||||||
std::cerr << result.error() << std::flush;
|
std::cerr << result.error() << std::flush;
|
||||||
|
@ -667,6 +667,8 @@ struct Note
|
|||||||
|
|
||||||
bool operator==(Note const&) const;
|
bool operator==(Note const&) const;
|
||||||
|
|
||||||
|
std::partial_ordering operator<=>(Note const&) const;
|
||||||
|
|
||||||
/// Simplify note by adding base to octave if octave is present
|
/// Simplify note by adding base to octave if octave is present
|
||||||
void simplify_inplace();
|
void simplify_inplace();
|
||||||
};
|
};
|
||||||
@ -714,7 +716,6 @@ struct Value
|
|||||||
/// Using Explicit_Bool to prevent from implicit casts
|
/// Using Explicit_Bool to prevent from implicit casts
|
||||||
static Value from(Explicit_Bool b);
|
static Value from(Explicit_Bool b);
|
||||||
|
|
||||||
|
|
||||||
static Value from(Number n); ///< Create value of type number holding provided number
|
static Value from(Number n); ///< Create value of type number holding provided number
|
||||||
static Value from(std::string s); ///< Create value of type symbol holding provided symbol
|
static Value from(std::string s); ///< Create value of type symbol holding provided symbol
|
||||||
static Value from(std::string_view s); ///< Create value of type symbol holding provided symbol
|
static Value from(std::string_view s); ///< Create value of type symbol holding provided symbol
|
||||||
@ -777,6 +778,8 @@ struct Value
|
|||||||
usize size() const;
|
usize size() const;
|
||||||
|
|
||||||
bool operator==(Value const& other) const;
|
bool operator==(Value const& other) const;
|
||||||
|
|
||||||
|
std::partial_ordering operator<=>(Value const& other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<Value::Type>
|
template<Value::Type>
|
||||||
|
49
src/value.cc
49
src/value.cc
@ -249,6 +249,44 @@ usize Value::size() const
|
|||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::partial_ordering Value::operator<=>(Value const& rhs) const
|
||||||
|
{
|
||||||
|
// TODO Block - array comparison should be allowed
|
||||||
|
if (type != rhs.type) {
|
||||||
|
return std::partial_ordering::unordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Nil:
|
||||||
|
return std::partial_ordering::equivalent;
|
||||||
|
|
||||||
|
case Type::Bool:
|
||||||
|
return b <=> rhs.b;
|
||||||
|
|
||||||
|
case Type::Symbol:
|
||||||
|
return s <=> rhs.s;
|
||||||
|
|
||||||
|
case Type::Number:
|
||||||
|
return n <=> rhs.n;
|
||||||
|
|
||||||
|
case Type::Array:
|
||||||
|
return std::lexicographical_compare_three_way(
|
||||||
|
array.elements.begin(), array.elements.end(),
|
||||||
|
rhs.array.elements.begin(), rhs.array.elements.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
case Type::Music:
|
||||||
|
return chord.notes.front() <=> rhs.chord.notes.front();
|
||||||
|
|
||||||
|
// Block should be compared but after evaluation so for now it's Type::Block
|
||||||
|
case Type::Block:
|
||||||
|
case Type::Intrinsic:
|
||||||
|
return std::partial_ordering::unordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, Value const& v)
|
std::ostream& operator<<(std::ostream& os, Value const& v)
|
||||||
{
|
{
|
||||||
switch (v.type) {
|
switch (v.type) {
|
||||||
@ -391,6 +429,16 @@ void Note::simplify_inplace()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::partial_ordering Note::operator<=>(Note const& rhs) const
|
||||||
|
{
|
||||||
|
if (octave.has_value() == rhs.octave.has_value()) {
|
||||||
|
if (octave.has_value())
|
||||||
|
return (12 * *octave) + base <=> (12 * *rhs.octave) + rhs.base;
|
||||||
|
return base <=> rhs.base;
|
||||||
|
}
|
||||||
|
return std::partial_ordering::unordered;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, Note note)
|
std::ostream& operator<<(std::ostream& os, Note note)
|
||||||
{
|
{
|
||||||
note.simplify_inplace();
|
note.simplify_inplace();
|
||||||
@ -401,7 +449,6 @@ std::ostream& operator<<(std::ostream& os, Note note)
|
|||||||
if (note.length) {
|
if (note.length) {
|
||||||
os << ":len=" << *note.length;
|
os << ":len=" << *note.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user