import { Notation } from "../notation" ; import Decimal from "break_infinity.js" ; const LOG4 = Math . log10 ( 4 ) ; const NUMBERS = [ "4-4" , "4÷4" , "√4" , "4-4÷4" , "4" , "4+4÷4" , "4!÷4" , "(4!+4)÷4" , "4+4" , "4+4+4÷4" , "4!÷4+4" , "44÷4" , "4!÷√4" , "44÷4+√4" , "4×4-√4" , "4×4-4÷4" ] ; export class FoursNotation extends Notation { public get name ( ) : string { return "Fours" ; } public get negativeInfinite ( ) : string { return "-∞" ; } public get infinite ( ) : string { return "∞" ; } public formatVerySmallNegativeDecimal ( val ) { return this . formatNegativeDecimal ( val ) ; } public formatVerySmallDecimal ( val ) { return this . formatDecimal ( val ) ; } public formatNegativeUnder1000 ( val ) { const str = this . formatUnder1000 ( val ) ; return `-${ this . bracketify ( str ) }` ; } public formatUnder1000 ( val ) { const exponent = Math . log10 ( val ) ; if ( val === 0 ) { return NUMBERS [ 0 ] ; } if ( exponent < 0 ) { return this . formatAsFraction ( new Decimal ( val ) ) ; } return this . formatAsInteger ( val ) ; } public formatNegativeDecimal ( val ) { const str = this . formatDecimal ( val ) ; return `-${ this . bracketify ( str ) }` ; } public formatDecimal ( val ) { if ( val . sign ( ) < 0 ) { return this . formatNegativeDecimal ( Decimal . minus ( 0 , val ) ) ; } const exponent = val . log10 ( ) ; const absoluteExponent = Math . abs ( exponent ) ; if ( absoluteExponent >= 24 ) { return this . formatAsPow ( val ) ; } if ( absoluteExponent >= 3 ) { return this . formatAsRoot ( val ) ; } return this . formatUnder1000 ( val . toNumber ( ) ) ; } private formatAsPow ( val ) { const power = val . log10 ( ) / LOG4 ; const powerStr = this . formatDecimal ( new Decimal ( power ) ) ; return `4^${ this . bracketify ( powerStr ) }` ; } private formatAsRoot ( val ) { const root = Decimal . sqrt ( val ) ; const str = this . formatDecimal ( root ) ; return `(${ str })^${ NUMBERS [ 2 ] }` ; } private formatAsInteger ( val ) { if ( val >= 16 ) { const quotient = Math . floor ( val / 16 ) ; const remainder = Math . floor ( Math . max ( 0 , Math . min ( 15 , val - quotient * 16 ) ) ) ; const pre = remainder === 0 ? "" : `${ NUMBERS [ Math . floor ( remainder ) ] }+` ; const suf = quotient === 1 ? "" : `×${ this . multiBracketify ( this . formatAsInteger ( quotient ) ) }` ; return `${ pre }4×4${ suf }` ; } return NUMBERS [ Math . floor ( val ) ] ; } private formatAsFraction ( val ) { const reciprocal = Decimal . div ( 4 , val ) ; const denominator = this . formatDecimal ( reciprocal ) ; return `4÷${ this . bracketify ( denominator ) }` ; } private bracketify ( str ) { if ( ( str . match ( /[\+\-\×÷\^]/ ) || [ "^" ] ) [ 0 ] !== "^" ) { return `(${ str })` ; } return str ; } private multiBracketify ( str ) { let bracketLayer = 0 ; for ( let i = 0 ; i < str . length ; i ++ ) { const char = str . charAt ( i ) ; if ( [ "+" , "-" ] . includes ( char ) && bracketLayer === 0 ) { return `(${ str })` ; } bracketLayer += this . bracket ( char ) ; } return str ; } private bracket ( char ) { switch ( char ) { case "(" : return 1 ; case ")" : return - 1 ; default : return 0 ; } } }