comp-library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub luzhiled1333/comp-library

:heavy_check_mark: src/utility/class/dice.hpp

Depends on

Verified with

Code

#pragma once

#include "src/cpp-template/header/rep.hpp"
#include "src/cpp-template/header/size-alias.hpp"

#include <array>
#include <cassert>
#include <vector>

namespace luz {

  template < typename T >
  class Dice {
    // +x, -x, +y, -y, +z, -z
    std::vector< T > dice;

    static constexpr std::array< std::array< T, 4 >, 6 > rot{
        {{2, 5, 3, 4},
         {4, 3, 5, 2},
         {4, 1, 5, 0},
         {0, 5, 1, 4},
         {0, 3, 1, 2},
         {2, 1, 3, 0}}};

    void rotate(const std::array< T, 4 > &idxs) {
      for (usize i: rep(1, 4)) {
        std::swap(dice[idxs[i - 1]], dice[idxs[i]]);
      }
    }

    void internal_rotate(usize base, isize count) {
      if (count != 0) {
        bool neg = count < 0;
        rotate(rot[base + neg]);
        internal_rotate(base, count + (neg ? +1 : -1));
      }
    }

    isize count_minimize(isize count) {
      return (count % 4 + 5) % 4 - 1;
    }

   public:
    Dice(): dice(6) {}
    Dice(T px, T nx, T py, T ny, T pz, T nz)
        : dice({px, nx, py, ny, pz, nz}) {}

    void rotate_x(isize count) {
      internal_rotate(0, count_minimize(count));
    }
    void rotate_y(isize count) {
      internal_rotate(2, count_minimize(count));
    }
    void rotate_z(isize count) {
      internal_rotate(4, count_minimize(count));
    }

    void rotate_by_id(usize idx) {
      rotate(rot[idx]);
    }

    T &right() {
      return dice[0];
    }
    T &left() {
      return dice[1];
    }
    T &back() {
      return dice[2];
    }
    T &front() {
      return dice[3];
    }
    T &top() {
      return dice[4];
    }
    T &bottom() {
      return dice[5];
    }

    T &face_id(usize idx) {
      assert(idx < 6);
      return dice[idx];
    }

    void normalize_as_top_front(T t, T f) {
      for (usize i: rep(0, 6)) {
        if (top() == t) {
          for ([[maybe_unused]] usize _: rep(0, 4)) {
            if (front() == f) return;
            rotate_z(1);
          }
        }

        rotate_by_id(2 * (i & 1));
      }

      assert(false);
    }
  };

  template < typename T >
  std::vector< Dice< T > > dice_enumeration(Dice< T > dice) {
    std::vector< Dice< T > > result;

    for (usize i: rep(0, 6)) {
      for ([[maybe_unused]] usize _: rep(0, 4)) {
        result.emplace_back(dice);
        dice.rotate_z(1);
      }

      dice.rotate_by_id(2 * (i & 1));
    }

    return result;
  }

} // namespace luz
#line 2 "src/utility/class/dice.hpp"

#line 2 "src/cpp-template/header/rep.hpp"

#line 2 "src/cpp-template/header/size-alias.hpp"

#include <cstddef>

namespace luz {

  using isize = std::ptrdiff_t;
  using usize = std::size_t;

} // namespace luz
#line 4 "src/cpp-template/header/rep.hpp"

#include <algorithm>

namespace luz {

  struct rep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept: i(i) {}
      void operator++() noexcept {
        ++i;
      }
      constexpr usize operator*() const noexcept {
        return i;
      }
      constexpr bool operator!=(const itr x) const noexcept {
        return i != x.i;
      }
    };
    const itr f, l;
    constexpr rep(const usize f, const usize l) noexcept
        : f(std::min(f, l)),
          l(l) {}
    constexpr auto begin() const noexcept {
      return f;
    }
    constexpr auto end() const noexcept {
      return l;
    }
  };

  struct rrep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept: i(i) {}
      void operator++() noexcept {
        --i;
      }
      constexpr usize operator*() const noexcept {
        return i;
      }
      constexpr bool operator!=(const itr x) const noexcept {
        return i != x.i;
      }
    };
    const itr f, l;
    constexpr rrep(const usize f, const usize l) noexcept
        : f(l - 1),
          l(std::min(f, l) - 1) {}
    constexpr auto begin() const noexcept {
      return f;
    }
    constexpr auto end() const noexcept {
      return l;
    }
  };

} // namespace luz
#line 5 "src/utility/class/dice.hpp"

#include <array>
#include <cassert>
#include <vector>

namespace luz {

  template < typename T >
  class Dice {
    // +x, -x, +y, -y, +z, -z
    std::vector< T > dice;

    static constexpr std::array< std::array< T, 4 >, 6 > rot{
        {{2, 5, 3, 4},
         {4, 3, 5, 2},
         {4, 1, 5, 0},
         {0, 5, 1, 4},
         {0, 3, 1, 2},
         {2, 1, 3, 0}}};

    void rotate(const std::array< T, 4 > &idxs) {
      for (usize i: rep(1, 4)) {
        std::swap(dice[idxs[i - 1]], dice[idxs[i]]);
      }
    }

    void internal_rotate(usize base, isize count) {
      if (count != 0) {
        bool neg = count < 0;
        rotate(rot[base + neg]);
        internal_rotate(base, count + (neg ? +1 : -1));
      }
    }

    isize count_minimize(isize count) {
      return (count % 4 + 5) % 4 - 1;
    }

   public:
    Dice(): dice(6) {}
    Dice(T px, T nx, T py, T ny, T pz, T nz)
        : dice({px, nx, py, ny, pz, nz}) {}

    void rotate_x(isize count) {
      internal_rotate(0, count_minimize(count));
    }
    void rotate_y(isize count) {
      internal_rotate(2, count_minimize(count));
    }
    void rotate_z(isize count) {
      internal_rotate(4, count_minimize(count));
    }

    void rotate_by_id(usize idx) {
      rotate(rot[idx]);
    }

    T &right() {
      return dice[0];
    }
    T &left() {
      return dice[1];
    }
    T &back() {
      return dice[2];
    }
    T &front() {
      return dice[3];
    }
    T &top() {
      return dice[4];
    }
    T &bottom() {
      return dice[5];
    }

    T &face_id(usize idx) {
      assert(idx < 6);
      return dice[idx];
    }

    void normalize_as_top_front(T t, T f) {
      for (usize i: rep(0, 6)) {
        if (top() == t) {
          for ([[maybe_unused]] usize _: rep(0, 4)) {
            if (front() == f) return;
            rotate_z(1);
          }
        }

        rotate_by_id(2 * (i & 1));
      }

      assert(false);
    }
  };

  template < typename T >
  std::vector< Dice< T > > dice_enumeration(Dice< T > dice) {
    std::vector< Dice< T > > result;

    for (usize i: rep(0, 6)) {
      for ([[maybe_unused]] usize _: rep(0, 4)) {
        result.emplace_back(dice);
        dice.rotate_z(1);
      }

      dice.rotate_by_id(2 * (i & 1));
    }

    return result;
  }

} // namespace luz
Back to top page