Skip to content

Instantly share code, notes, and snippets.

@awnion
Last active December 18, 2021 19:20
Show Gist options
  • Save awnion/6ca26d9dbaf6fec64e6b8e0c873805b0 to your computer and use it in GitHub Desktop.
Save awnion/6ca26d9dbaf6fec64e6b8e0c873805b0 to your computer and use it in GitHub Desktop.

C++

from here

#ifndef ANALOGLITERALS_HPP
#define ANALOGLITERALS_HPP

namespace analog_literals {

typedef unsigned int uint;

// Symbols

  enum line_end { o, I };
  enum Lsymbol { L };

// Intermediary types used during construction

  struct eLsymbol {};
  eLsymbol operator! (Lsymbol) { return eLsymbol(); }

  struct gen { template <typename T> operator T () const { return T(); } };

  template <typename T, uint n> struct excls { excls<T, n + 1> operator! () const { return gen(); } };

  template <typename T, uint n> struct dashes: excls<dashes<T, n>, 0>
  { dashes<T, n + 1> operator-- (int) const { return gen(); } };

  template <typename, uint> struct L_symbols {}; // represents a L|L|L|.. series
  template <typename T, uint n> L_symbols<T, n + 1> operator| (L_symbols<T, n>, Lsymbol) { return gen(); }

  template <typename, uint> struct eL_symbols {}; // represents a !L|!L|!L|.. series
  template <typename T, uint n> eL_symbols<T, n + 1> operator| (eL_symbols<T, n>, eLsymbol) { return gen(); }

  dashes<line_end, 1> operator-- (line_end, int) { return gen(); }
  excls<line_end, 1> operator! (line_end) { return gen(); }

// Result types

  template <uint len> struct line: L_symbols<line<len>, 0>
  { static uint const length; operator uint () const { return len; } };
  template <uint x, uint y> struct rectangle { static uint const width, height, area; };
  template <uint x, uint y, uint z> struct cuboid { static uint const width, height, depth, volume; };

// Static members

  template <uint len> uint const line<len>::length = len;

  template <uint x, uint y> uint const rectangle<x, y>::width = x;
  template <uint x, uint y> uint const rectangle<x, y>::height = y;
  template <uint x, uint y> uint const rectangle<x, y>::area = x * y;

  template <uint x, uint y, uint z> uint const cuboid<x, y, z>::width = x;
  template <uint x, uint y, uint z> uint const cuboid<x, y, z>::height = y;
  template <uint x, uint y, uint z> uint const cuboid<x, y, z>::depth = z;
  template <uint x, uint y, uint z> uint const cuboid<x, y, z>::volume = x * y * z;

  template <uint x, uint y, uint z> rectangle<x, y> front (cuboid<x, y, z>) { return gen(); }
  template <uint x, uint y, uint z> rectangle<z, y> side (cuboid<x, y, z>) { return gen(); }
  template <uint x, uint y, uint z> rectangle<x, z> top (cuboid<x, y, z>) { return gen(); }

// Equality

  template <uint ax, uint bx> bool operator== (line<ax>, line<bx>) { return ax == bx; }

  template <uint ax, uint ay, uint bx, uint by> bool operator== (rectangle<ax, ay>, rectangle<bx, by>)
  { return ax == bx && ay == by; }

  template <uint ax, uint ay, uint az, uint bx, uint by, uint bz>
  bool operator== (cuboid<ax, ay, az>, cuboid<bx, by, bz>) { return ax == bx && ay == by && az == bz; }

// Construction

  // line

  line<0> operator- (line_end, line_end) { return gen(); }
  template <uint x> line<x> operator- (dashes<line_end, x>, line_end) { return gen(); }

  // rectangle

  template <uint x, uint y> struct lower_rectangle {}; // with lower right corner

  template <uint excl_marks, uint x>
  lower_rectangle<x, (excl_marks + 1) / 2> operator- (excls<dashes<line_end, x>, excl_marks>, line_end)
  { return gen(); }

  template <uint x, uint y> rectangle<x, y> operator| (line<x>, lower_rectangle<x, y>) { return gen(); }

  // cuboid

  template <uint x, uint y, uint z> struct cuboid_top {};
  template <uint x, uint y, uint z> struct half_cuboid {};
    // dimensions of complete cuboid known, rest is for show

  template <uint x, uint n>
  cuboid_top<x, n + 1, n> operator| (L_symbols<line<x>, n>, line<x>) { return gen(); }

  template <uint x, uint y, uint z, uint n>
  eL_symbols<half_cuboid<x, y + (n + 1) / 3, z>, 0> // todo: assert: n%3=2
    operator| (cuboid_top<x, y, z>, excls<line_end, n>) { return gen(); }

  template <uint x, uint y, uint z>
  cuboid<x, y, z> operator| (eL_symbols<half_cuboid<x, y, z>, z>, lower_rectangle<x, 1>) { return gen(); }

// Convenience namespaces that can be "using namespace"'d:

  namespace symbols
  {
    using analog_literals::o;
    using analog_literals::I;
    using analog_literals::L;
  }

  namespace shapes
  {
    using analog_literals::line;
    using analog_literals::rectangle;
    using analog_literals::cuboid;
  }

} // analog_literals

#endif // header guard

#ifdef ANALOGLITERALS_TEST

int main ()
{
  using namespace analog_literals::symbols;
  using namespace analog_literals::shapes;

  line<3>(I-------I);

  rectangle<2, 3>(o-----o
                  |     !
                  !     !
                  !     !
                  o-----o);

  cuboid<6, 6, 3>(o-------------o
                  |L             \
                  | L             \
                  |  L             \
                  |   o-------------o
                  |   !             !
                  !   !             !
                  o   |             !
                   L  |             !
                    L |             !
                     L|             !
                      o-------------o );

  cuboid<3, 4, 2>(o-------o
                  |L       \
                  | L       \
                  |  o-------o
                  |  !       !
                  o  |       !
                   L |       !
                    L|       !
                     o-------o);
}

#endif // testing

Python

class Line(object):
    def __init__(self, x):
        self.x = x

    def __neg__(self):
        return Line(self.x + 1)

    def __sub__(self, other):
        return Line(self.x + other.x + 1)

    def __pos__(self):
        return Area(self.x, 1)

    def __add__(self, other):
        assert self.x == other.x
        return Area(self.x, other.y + 1)

    def __int__(self):
        return self.x

class Area(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __pos__(self):
        return Area(self.x, self.y + 1)

    def __int__(self):
        return self.x * self.y

I = Line(1)

assert 6 == int(I----I)

assert 24 == int((I----I)
                  +    +
                  +    + 
                 (I----I))

LISP

(defparameter *x-scale* (/ 1 2)) ; cos - is smaller than !
(defparameter *y-scale* 1)
(defparameter *z-scale* 2)

(defun line-value (symbols)
  (list (* (loop for char across (symbol-name (first symbols))
              summing (ecase char (#\- 1) (#\I 0)))
           *x-scale*)))

(defun rectangle-value (symbols)
  (let ((x 0) (y 0))
    (dolist (sym symbols)
      (map 'nil (lambda (char)
                  (ecase char
                    (#\- (incf x (/ 1 2)))
                    (#\! (incf y (/ 1 2)))
                    (#\+ nil)))
           (symbol-name sym)))
    (list (* x *x-scale*) (* y *y-scale*))))

(defun cuboid-value (symbols)
  (let ((x 0) (y 0) (z 0))
    (dolist (sym symbols)
      (map 'nil (lambda (char)
                  (ecase char
                    (#\- (incf x (/ 1 3)))
                    (#\! (incf y (/ 1 3)))
                    (#\/ (incf z (/ 1 3)))
                    (#\* nil)))
           (symbol-name sym)))
    (list (* x *x-scale*) (* y *y-scale*) (* z *z-scale*))))

(defmacro as-literal (&rest symbols)
  `(list ,@(ecase (aref (symbol-name (first symbols)) 0)
                  (#\I (line-value symbols))
                  (#\+ (rectangle-value symbols))
                  (#\* (cuboid-value symbols)))))

(as-literal *------*
           /      /!
          /      / !
         *------*  !
         !      !  *
         !      ! /
         !      !/
         *------* ) => (3 3 4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment