{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"A\", \"ABILITY\", \"ABLE\", \"ABOUT\", \"ABOVE\", \"ABSENCE\", \"ABSOLUTELY\", \"ACADEMIC\", \"ACCEPT\", \"ACCESS\", \"ACCIDENT\"]"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "words = File.read(\"p042_words.txt\").split(\",\").map {|w| w[1..-2]}\n",
    "words[0..10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":grow"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require 'singleton'\n",
    "\n",
    "class TriangleN\n",
    "  include Enumerable\n",
    "  include Singleton\n",
    "\n",
    "  def initialize\n",
    "    @tns = [1]\n",
    "  end\n",
    "  \n",
    "  def is_triangle?(n)\n",
    "    self.grow(n)\n",
    "    @tns.include?(n)\n",
    "  end\n",
    "  \n",
    "  def grow(n)\n",
    "    while n > @tns[-1]\n",
    "      @tns += [(@tns.length+1) * (@tns.length+2) / 2]\n",
    "    end\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "#<TriangleN:0x00563e39321180 @tns=[1]>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trins = TriangleN.instance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trins.is_triangle? 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trins.is_triangle? 11"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":triangle_sum?"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class String\n",
    "  \n",
    "  @@triangles = TriangleN.instance\n",
    "  \n",
    "  def to_nums\n",
    "    self.chars.map {|c| c.ord - 'A'.ord + 1}\n",
    "  end\n",
    "  \n",
    "  def num_sum\n",
    "    self.to_nums.sum\n",
    "  end\n",
    "  \n",
    "  def triangle_sum?\n",
    "    @@triangles.is_triangle?(self.num_sum)\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[19, 11, 25]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"SKY\".to_nums"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"SKY\".num_sum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trins.is_triangle? \"SKY\".num_sum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"SKY\".triangle_sum?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "162"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "words.select {|w| w.triangle_sum?}.length"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"A\", \"ABILITY\", \"ABOVE\", \"ACCOMPANY\", \"ACHIEVEMENT\", \"AGENCY\", \"AGREE\", \"AIR\", \"ALREADY\", \"AN\", \"ANCIENT\", \"APPARENT\", \"APPOINT\", \"APPROACH\", \"ASSUME\", \"AT\", \"ATMOSPHERE\", \"BAG\", \"BAND\", \"BANK\", \"BAR\", \"BEAT\", \"BELONG\", \"BENEATH\", \"BONE\", \"BOTH\", \"BRIDGE\", \"BUILDING\", \"BURN\", \"CALL\", \"CAPACITY\", \"CAREFUL\", \"CASE\", \"CHILD\", \"CIVIL\", \"CLOSELY\", \"COME\", \"CONFIDENCE\", \"CONFIRM\", \"CONSERVATIVE\", \"CONSTRUCTION\", \"CONTENT\", \"COULD\", \"CURRENTLY\", \"DECISION\", \"DEFINITION\", \"DEMOCRATIC\", \"DEPUTY\", \"DESPITE\", \"DISTINCTION\", \"EAST\", \"EDGE\", \"EDUCATIONAL\", \"EFFECT\", \"EQUIPMENT\", \"EVENT\", \"FACE\", \"FAIL\", \"FAMILY\", \"FEEL\", \"FIELD\", \"FIGURE\", \"FLOOR\", \"FREEDOM\", \"FUND\", \"FUTURE\", \"GENTLEMAN\", \"GREY\", \"GROWTH\", \"HAIR\", \"HAPPY\", \"HAVE\", \"HERE\", \"HIS\", \"IF\", \"INCIDENT\", \"INCREASED\", \"INCREASINGLY\", \"INDIVIDUAL\", \"INSTRUMENT\", \"INTEND\", \"INTENTION\", \"IS\", \"LAW\", \"LEADER\", \"LEAVE\", \"LENGTH\", \"LESS\", \"LITTLE\", \"LOVELY\", \"MAN\", \"MATCH\", \"MERELY\", \"MILK\", \"MISTAKE\", \"MOVE\", \"MUCH\", \"NEED\", \"NOTICE\", \"OBJECT\", \"OBJECTIVE\", \"OF\", \"OIL\", \"ONLY\", \"OTHER\", \"OURSELVES\", \"PART\", \"PASS\", \"PATH\", \"PERFORM\", \"PRISON\", \"PRIVATE\", \"PROBABLY\", \"PROCEDURE\", \"QUALITY\", \"QUESTION\", \"RANGE\", \"READ\", \"REAL\", \"RELIEF\", \"REMOVE\", \"REPRESENT\", \"REQUEST\", \"RESPOND\", \"RIDE\", \"SAMPLE\", \"SAY\", \"SEAT\", \"SECURITY\", \"SINGLE\", \"SKY\", \"SOIL\", \"SOLICITOR\", \"SONG\", \"SOUTHERN\", \"SPIRIT\", \"START\", \"SUGGESTION\", \"TALL\", \"TAX\", \"THEORY\", \"THREATEN\", \"THROUGHOUT\", \"TITLE\", \"TOOTH\", \"TOTALLY\", \"TRAVEL\", \"TYPE\", \"UNABLE\", \"UNDERSTAND\", \"UPON\", \"USE\", \"VARIOUS\", \"VARY\", \"VIDEO\", \"WAGE\", \"WARM\", \"WATCH\", \"WE\", \"WHILST\", \"WIDELY\", \"WOMAN\"]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "words.select {|w| w.triangle_sum?}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"#<TriangleN:0x00563e39321180 @tns=[1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210]>\""
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trins.inspect"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.4.0",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.4.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}