Struct bellframe::row::Row [−][src]
pub struct Row { /* fields omitted */ }
Expand description
A single Row
of Bell
s.
This can be viewed as a permutation of rounds on a given Stage
.
A Row
must always be valid according to
the Framework - i.e., it
must contain every Bell
up to its Stage
once and precisely once. This is only checked
in the constructors and then used as assumed knowledge to avoid further checks. This is
similar to how &str
and String
are required to be valid UTF-8.
Example
use proj_core::{Bell, Row, Stage, InvalidRowError}; // Create rounds on 8 bells. Rounds is always valid on any `Stage` let rounds_on_8 = Row::rounds(Stage::MAJOR); assert_eq!(rounds_on_8.stage(), Stage::MAJOR); assert_eq!(rounds_on_8.to_string(), "12345678"); // Parse a generic (valid) change from a string. Note how invalid // `char`s are skipped. This could fail if the resulting `Row` is // invalid, so we use ? to propogate that error out of the current // function. let queens = Row::parse("13579 | 24680")?; assert_eq!(queens.stage(), Stage::ROYAL); assert_eq!(queens.to_string(), "1357924680"); // If we try to parse an invalid `Row`, we get an error. This means // that we can assume that all `Row`s satisfy the Framework's definition assert_eq!( Row::parse("112345"), Err(InvalidRowError::DuplicateBell(Bell::from_name('1').unwrap())) );
Implementations
Creates a Row
from a Vec
of Bell
s, checking that the the resulting Row
is valid.
Example
use proj_core::{Bell, InvalidRowError, Row}; // Converting a `Row` from a valid `Vec` of `Bell`s is fine assert_eq!( Row::from_vec(vec![ Bell::from_name('4').unwrap(), Bell::from_name('2').unwrap(), Bell::from_name('1').unwrap(), Bell::from_name('3').unwrap(), ])?.to_string(), "4213" ); // Converting a `Row` from an invalid `Vec` of `Bell`s is not so fine assert_eq!( Row::from_vec(vec![ Bell::from_name('4').unwrap(), Bell::from_name('2').unwrap(), Bell::from_name('1').unwrap(), Bell::from_name('4').unwrap(), ]), Err(InvalidRowError::DuplicateBell(Bell::from_name('4').unwrap())) );
Creates a Row
from a Vec
of Bell
s, without checking that the the resulting
Row
is valid. Only use this if you’re certain that the input is valid, since performing
invalid operations on Row
s is undefined behaviour.
Safety
This function is safe if bells
corresponds to a valid Row
according to the CC’s
Framework. This means that each Bell
is unique, and has index
smaller
than the bells.len()
.
Example
use proj_core::{Bell, InvalidRowError, Row}; // Converting a `Row` from a valid `Vec` of `Bell`s is fine, but still unsafe assert_eq!( unsafe { Row::from_vec_unchecked(vec![ Bell::from_name('4')?, Bell::from_name('2')?, Bell::from_name('1')?, Bell::from_name('3')?, ]) }.to_string(), "4213" ); // Converting a `Row` from an invalid `Vec` of `Bell`s compiles and runs, // but silently creates an invalid `Row` assert_eq!( unsafe { Row::from_vec_unchecked(vec![ Bell::from_name('4')?, Bell::from_name('2')?, Bell::from_name('1')?, Bell::from_name('4')?, ]) }.to_string(), "4214" );
Utility function that creates a Row
from an iterator of Bell
s, without performing
the validity check. This function is unsafe
; only use it if you can guarantee that the
resulting Row
is valid.
Safety
This function is safe if iter
yields a valid Row
according to the CC’s Framework. This
means that each Bell
is unique, and has index
smaller than the number
of items yeilded by iter
.
Example
use proj_core::{Bell, Row, Stage, InvalidRowError}; // Create a valid row from an iterator over `Bell`s let iter = [0, 3, 4, 2, 1].iter().copied().map(Bell::from_index); let row = unsafe { Row::from_iter_unchecked(iter) }; assert_eq!(row.to_string(), "14532"); // Create an invalid row from an iterator over `Bell`s. We get no error, // but doing anything with the resulting `Row` is undefined behaviour let iter = [0, 3, 7, 2, 1].iter().copied().map(Bell::from_index); let row = unsafe { Row::from_iter_unchecked(iter) }; assert_eq!(row.to_string(), "14832");
Returns the Stage
of this Row
.
Example
use proj_core::{Row, Stage}; // Rounds on a given `Stage` should have that `Stage` assert_eq!(Row::rounds(Stage::MINIMUS).stage(), Stage::MINIMUS); assert_eq!(Row::rounds(Stage::SEPTUPLES).stage(), Stage::SEPTUPLES); assert_eq!(Row::parse("41325")?.stage(), Stage::DOUBLES); assert_eq!(Row::parse("321 654 987 0")?.stage(), Stage::ROYAL);
Multiply two Row
s (i.e. use the RHS to permute the LHS), but without checking that the
Stage
s are compatible. This is slighlty faster than using *
or Row::mul
, but is
unsafe
: the output is not guaruteed to be valid unless both inputs have the same
Stage
.
Safety
This is safe if the two Row
s have the same Stage
(which is often an invariant
enforced by other datatypes, such as Block
).
Example
use proj_core::{Bell, Row, Stage, IncompatibleStages}; // Multiplying two Rows of the same Stage is OK, but still unsafe assert_eq!( unsafe { Row::parse("13425678")?.mul_unchecked(&Row::parse("43217568")?) }, Row::parse("24317568")? ); // Multiplying two Rows of different Stages is not OK, and creates an invalid Row. // Note how both sides of the `assert_eq` have to use unsafe to create an invalid Row. assert_eq!( unsafe { Row::parse("13475628")?.mul_unchecked(&Row::parse("4321")?) }, unsafe {Row::from_vec_unchecked( [7, 4, 3, 1].iter().map(|&x| Bell::from_number(x).unwrap()).collect() )} );
Find the inverse of a Row
. If X
is the input Row
, and Y = !X
, then
XY = YX = I
where I
is the identity on the same stage as X
(i.e. rounds). This
operation cannot fail, since valid Row
s are guaruteed to have an inverse.
Example
use proj_core::{Row, Stage}; // The inverse of Queens is Tittums assert_eq!(!Row::parse("135246")?, Row::parse("142536")?); // Backrounds is self-inverse assert_eq!(!Row::backrounds(Stage::MAJOR), Row::backrounds(Stage::MAJOR)); // `1324` inverts to `1423` assert_eq!(!Row::parse("1342")?, Row::parse("1423")?);
Calculate the inverse of this Row
, storing the result in an existing Row
(thus making
use of its allocation). This resizes out
to make it the right Stage
to take the
output value.
Example
use proj_core::{Row, Stage}; // Create a new row that will be overwritten to avoid reallocations let mut row_buf = Row::empty(); // The inverse of Queens is Tittums Row::parse("135246")?.inv_into(&mut row_buf); assert_eq!(row_buf, Row::parse("142536")?); // Backrounds is self-inverse Row::backrounds(Stage::MAJOR).inv_into(&mut row_buf); assert_eq!(row_buf, Row::backrounds(Stage::MAJOR)); // `1324` inverts to `1423` Row::parse("1342")?.inv_into(&mut row_buf); assert_eq!(row_buf, Row::parse("1423")?);
Swap two Bell
s round in this Row
, panicking if either of the indices point out of
bounds.
Example
use proj_core::{Row, Stage}; let mut rounds = Row::rounds(Stage::MAJOR); assert_eq!(rounds.to_string(), "12345678"); rounds.swap(0, 1); // Note we are using 0-indexing assert_eq!(rounds.to_string(), "21345678"); rounds.swap(2, 5); // Note we are using 0-indexing assert_eq!(rounds.to_string(), "21645378");
Extend this Row
in-place with cover bells so that it has a given Stage
Parse a string into a Row
, skipping any char
s that aren’t valid bell names. This
returns Err(
InvalidRowError
)
if the Row
would be invalid.
Example
use proj_core::{Bell, Row, Stage, InvalidRowError}; // Parsing a valid Row is fine assert_eq!(Row::parse("12543")?.to_string(), "12543"); // Parsing valid rows with invalid characters is also fine assert_eq!(Row::parse("4321\t[65 78]")?.to_string(), "43216578"); assert_eq!(Row::parse("3|2|1 6|5|4 9|8|7")?.to_string(), "321654987"); // Parsing an invalid `Row` returns an error describing the problem assert_eq!( Row::parse("112345"), Err(InvalidRowError::DuplicateBell(Bell::from_number(1).unwrap())) ); assert_eq!( Row::parse("12745"), Err(InvalidRowError::BellOutOfStage( Bell::from_number(7).unwrap(), Stage::DOUBLES )) );
Parse a string into a Row
, extending to the given Stage
if required and skipping any
char
s that aren’t valid bell names. This returns Err(
InvalidRowError
)
if the
Row
would be invalid, and this will produce better error messages than Row::parse
because of the extra information provided by the Stage
.
Example
use proj_core::{Bell, Row, Stage, InvalidRowError}; // Parsing a valid Row is fine assert_eq!(Row::parse("12543")?.to_string(), "12543"); // Parsing valid rows with invalid characters is also fine assert_eq!(Row::parse("4321\t[65 78]")?.to_string(), "43216578"); assert_eq!(Row::parse("3|2|1 6|5|4 9|8|7")?.to_string(), "321654987"); // Parsing an invalid `Row` returns an error describing the problem assert_eq!( Row::parse("112345"), Err(InvalidRowError::DuplicateBell(Bell::from_number(1).unwrap())) ); assert_eq!( Row::parse("12745"), Err(InvalidRowError::BellOutOfStage( Bell::from_name('7').unwrap(), Stage::DOUBLES )) );
Creates a Row
containing no Bell
s, but without causing any allocations. This is
useful for initialising temporary Row
s.
Utility function that creates a Row
from an iterator of Bell
s, performing the
validity check.
Example
use proj_core::{Bell, Row, Stage, InvalidRowError}; // Create a valid row from an iterator over `Bell`s let iter = [0, 3, 4, 2, 1].iter().copied().map(Bell::from_index); let row = Row::from_iter(iter)?; assert_eq!(row.to_string(), "14532"); // Attempt to create an invalid row from an iterator over `Bell`s // (we get an error) let iter = [0, 3, 7, 2, 1].iter().copied().map(Bell::from_index); assert_eq!( Row::from_iter(iter), Err(InvalidRowError::BellOutOfStage( Bell::from_name('8').unwrap(), Stage::DOUBLES, )) );
All the Row
s formed by repeatedly permuting a given Row
. The first item returned will
always be the input Row
, and the last will always be rounds
.
Example
use proj_core::{Row}; // The closure of "18234567" are all the fixed-treble cyclic part heads. assert_eq!( Row::parse("18234567")?.closure(), vec![ Row::parse("18234567")?, Row::parse("17823456")?, Row::parse("16782345")?, Row::parse("15678234")?, Row::parse("14567823")?, Row::parse("13456782")?, Row::parse("12345678")?, ] );
All the Row
s formed by repeatedly permuting a given Row
, but the first Row
returned
will always be rounds, rather than self
. This is useful for situations
like generating part heads, where it’s more intutive for the closure to start at rounds.
Example
use proj_core::{Row}; // The closure of "18234567" are all the fixed-treble cyclic part heads. // Note how rounds is the first Row/part head generated assert_eq!( Row::parse("18234567")?.closure_from_rounds(), vec![ Row::parse("12345678")?, Row::parse("18234567")?, Row::parse("17823456")?, Row::parse("16782345")?, Row::parse("15678234")?, Row::parse("14567823")?, Row::parse("13456782")?, ] );
pub fn multi_cartesian_product(
row_sets: impl IntoIterator<Item = Vec<Self>>
) -> Result<Vec<Self>, IncompatibleStages>
[src]
pub fn multi_cartesian_product(
row_sets: impl IntoIterator<Item = Vec<Self>>
) -> Result<Vec<Self>, IncompatibleStages>
[src]Takes a sequence of sets of Row
s ([X_1, X_2, ..., X_n]
) and computes every product
x_1 * x_2 * ... * x_n
where x_i
comes from X_i
for all i
.
pub fn least_group_containing<'a>(
rows: impl IntoIterator<Item = &'a Self> + Clone
) -> Result<HashSet<Self>, IncompatibleStages> where
Self: 'a,
[src]
pub fn least_group_containing<'a>(
rows: impl IntoIterator<Item = &'a Self> + Clone
) -> Result<HashSet<Self>, IncompatibleStages> where
Self: 'a,
[src]Generates the least group containing a given set of Row
s, returning the result in a
HashSet
(therefore, the result is unordered). The current algorithm is quite slow; if
anyone knows of a better one, then please let me know…
pub fn is_group<'a>(
rows: impl IntoIterator<Item = &'a Self>
) -> Result<bool, IncompatibleStages> where
Self: 'a,
[src]
pub fn is_group<'a>(
rows: impl IntoIterator<Item = &'a Self>
) -> Result<bool, IncompatibleStages> where
Self: 'a,
[src]Determines if the given set of Row
s forms a group. This performs n^2
transpositions
and n
inversions where n
is the number of unique elements yeilded by rows
. See this
Wikipedia page for the algorithm used.
Checks the validity of a potential Row
, returning it if valid and returning an
InvalidRowError
otherwise (consuming the potential Row
so it can’t be used).
Checks the validity of a potential Row
, extending it to the given Stage
if valid and
returning an InvalidRowError
otherwise (consuming the potential Row
so it can’t be
used). This will provide nicer errors than Row::check_validity
since this has extra
information about the desired Stage
of the potential Row
.
Gets the 0-indexed place at which a given Bell
appears in this Row
, returning
None
if the Bell
is out of the stage. This performs a linear search of the Row
.
Example
use proj_core::{Bell, Row}; let tittums = Row::parse("15263748").unwrap(); // The treble is leading in position 0 assert_eq!(tittums.place_of(Bell::from_name('1')?)?, 0); // The '5' is at index `1`, because indices always start from zero assert_eq!(tittums.place_of(Bell::from_name('5')?)?, 1);
Perform an in-place check that this Row
is equal to rounds. x.is_rounds()
is an
optimised version of x == Row::rounds(x.stage())
.
Example
use proj_core::{Row, Stage}; // Rounds is ... rounds (DOH) assert!(Row::rounds(Stage::MAXIMUS).is_rounds()); // This is not rounds assert!(!Row::parse("18423756")?.is_rounds());
Multiply two Row
s (i.e. use the RHS to permute the LHS), checking that the Stage
s are
compatible. This is like using [*
](Result
instead of panic!
ing.
Example
use proj_core::{Row}; // Multiplying two Rows of the same Stage is fine assert_eq!( Row::parse("13425678")?.mul(&Row::parse("43217568")?), Ok(Row::parse("24317568")?) ); // Multiplying two Rows of different Stages causes an error but no // undefined behaviour assert_eq!( &Row::parse("13425678")? .mul(&Row::parse("4321")?) .unwrap_err() .to_string(), "Incompatible stages: Major (lhs), Minimus (rhs)" );
Computes the value of r
which satisfies r * self = other
- i.e. the Row
which
pre-transposes self
to other
.
Concatenates the names of the Bell
s in this Row
to the end of a String
. Using
row.to_string()
will behave the same as this but will return an newly allocated
String
.
Example
use proj_core::{Row}; let waterfall = Row::parse("6543217890")?; let mut string = "Waterfall is: ".to_owned(); waterfall.push_to_string(&mut string); assert_eq!(string, "Waterfall is: 6543217890");
A very collision-resistant hash function. It is guarunteed to be perfectly
collision-resistant on the following Stage
s:
- 16-bit machines: Up to 6 bells
- 32-bit machines: Up to 9 bells
- 64-bit machines: Up to 16 bells
This hashing algorithm works by reading the row as a number using the stage as a base, thus
guarunteeing that (ignoring overflow), two Row
s will only be hashed to the same value
if they are in fact the same. This is ludicrously inefficient in terms of hash density,
but it is fast and perfect and in most cases will suffice.
Trait Implementations
Uses the RHS to permute the LHS without consuming either argument.
Example
use proj_core::{Row}; // Multiplying two Rows of the same Stage just returns a new Row assert_eq!( &Row::parse("13425678")? * &Row::parse("43217568")?, Row::parse("24317568")? );
use proj_core::{Row}; // Multiplying two Rows of different Stages panics rather than // producing undefined behaviour let _unrow = &Row::parse("13425678")? * &Row::parse("4321")?;
Find the inverse of a Row
. If X
is the input Row
, and Y = !X
, then
XY = YX = I
where I
is the identity on the same stage as X
(i.e. rounds). This
operation cannot fail, since valid Row
s are guaruteed to have an inverse.
Example
use proj_core::{Row, Stage}; // The inverse of Queens is Tittums assert_eq!(!Row::parse("135246")?, Row::parse("142536")?); // Backrounds is self-inverse assert_eq!(!Row::backrounds(Stage::MAJOR), Row::backrounds(Stage::MAJOR)); // `1324` inverts to `1423` assert_eq!(!Row::parse("1342")?, Row::parse("1423")?);
This method returns an ordering between self
and other
values if one exists. Read more
This method tests less than (for self
and other
) and is used by the <
operator. Read more
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
This method tests greater than (for self
and other
) and is used by the >
operator. Read more
Auto Trait Implementations
impl RefUnwindSafe for Row
impl UnwindSafe for Row
Blanket Implementations
Mutably borrows from an owned value. Read more