[
  {
    "path": ".gitignore",
    "content": "# OS generated files\n.DS_Store\nThumbs.db\n*~\n# Thumbnails\n._*\n\n### Java ###\n*.class\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n# Gradle Files\n.gradle\n.m2\n\n# Build output directies\nbuild/\n/target\n\n### Eclipse project file ###\n.metadata\n.classpath\n.project\n.settings/\nbin/\ntmp/\n*.tmp\n*.bak\n*.swp\n*~.nib\n.loadpath\n.launch\n.cproject\n\n\n# IntelliJ project files\n*.iml\n*.iws\n*.ipr\n.idea\nout\ntest-output\n\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# files intended to be ignored\n*IGNORE\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "README-MAVEN.txt",
    "content": "This file provides brief instructions on how to add this repository to\na Maven build, from Eclipse, NetBeans, IntelliJ, or the command line.\nSpecifically, it provides instructions on creating a version of algs4.jar\nthat you can use as a dependency in your projects.\n\nThese instructions assume that you already have installed Java 7\n(JDK 1.7) or above.\n\n\nUsing Maven in Eclipse for Java Developers\n------------------------------------------\nIf m2e (Maven plugin) is not built into Eclipse, follow these steps to install the plugin:\n\n  * Open Eclipse.\n  * Go to Help -> Eclipse Marketplace.\n  * Search for Maven.\n  * Click \"Install\" button at \"Maven Integration for Eclipse\" or \"m2e\" section.\n  * Follow the instruction step by step.,\n\nRestart Eclipse after installing m2e.\n\nNow you can import algs4 as \"Maven Project\" into Eclipse:\n\n  * Open menu: File-> Import-> Maven-> Existing Maven Projects...\n  * Choose directory of algs4.\n  * Confirm import.\n\nTo complete dependencies resolution after import:\n  * Right click on the project, choose Maven -> Update Project...\n  * Confirm project update.\n\nTo build project in Eclipse:\nEclipse automatically builds the project every time it saved.\nBut if you want enforce build, do following:\n  * Right click on the project in Eclipse.\n  * Choose Run as... Maven build.\n\nMaven will put algs4-<version>.jar in the directory <algs4 directory>/target.\nYou can use this jar as a dependency in your projects.\n\n\nUsing Maven in IntelliJ IDEA\n----------------------------\n\n\nUsing Maven in Netbeans\n-----------------------\n\n\nUsing Maven from the Windows Command Prompt\n-------------------------------------------\nDownload and install Maven by following the instructions at\nhttps://maven.apache.org.\n\nLocate the installation directory for Maven, e.g., C:\\<apache-maven-x-y-z>\n\nLocate the installation directory for Java, e.g., C:\\Program Files\\Java\\<JDK-x-y-z>\n\nSet the following environment variables:\n\nset JAVA_HOME=C:\\Program Files\\Java\\<JDK-x-y-z>\nset PATH=%JAVA_HOME%\\bin;%PATH%\nset M2_HOME=C:\\<apache-maven-x-y-z>\nset PATH=%M2_HOME%\\bin;%PATH%\n\nTo create the algs4-<version>.jar package and install it in the local\nrepository for reuse from other projects, change to the directory of\nthe algs4 repository and run Maven.\n\ncd <algs4 directory>\nmvn clean install\n\nMaven will put algs4-<version>.jar in the directory <algs4 directory>/target.\nYou can use this jar as a dependency in your projects.\n\n\n\nUsing Maven from the Linux / Mac OS X bash shell\n------------------------------------------------\nDownload and install Maven, either by using your favorite package\nmanager  (such as apt-get) or by following the instructions at\nhttps://maven.apache.org.\n\nLocate the installation directory for Maven, e.g., /my/maven/<apache-maven-x-y-z>\n\nLocate the installation directory for Java, e.g., /my/java/<JDK-x-y-z->\n\nSet the following environment variables:\n\nexport JAVA_HOME=/my/java/<JDK-x-y-z>\nexport PATH=$JAVA_HOME/bin:$PATH\nexport M2_HOME=/my/maven/<apache-maven-x-y-z>\nexport PATH=$M2_HOME/bin:$PATH\n\nTo create the algs4-<version>.jar package and install it in the local\nrepository for reuse from other projects, change to the directory of\nthe algs4 repository and run Maven.\n\ncd <algs4 directory>\nmvn clean install\n\nMaven will put algs4-<version>.jar in the directory <algs4 directory>/target.\nYou can use this jar as a dependency in your projects.\n\n"
  },
  {
    "path": "README.md",
    "content": "## Overview\n\n<IMG SRC=\"http://algs4.cs.princeton.edu/cover.png\"  align=right hspace=25 width=100 alt = \"Algorithms 4/e textbook\">\nThis <a href = \"https://github.com/kevin-wayne/algs4\">public repository</a>\ncontains the Java <a href = \"http://algs4.cs.princeton.edu/code/\">source code</a>\nfor the algorithms and clients in the textbook\n<a href = \"http://amzn.to/13VNJi7\">Algorithms, 4th Edition</a> by Robert Sedgewick and Kevin Wayne.\nThe official version at <a href = \"https://github.com/kevin-wayne/algs4\">https://github.com/kevin-wayne/algs4</a>\nis actively maintained and updated by the authors.\nThe programs are organized in the package <code>edu.princeton.cs.algs4</code>.\nIf you need only the class files (and not the source code), you can use\n<a href = \"http://algs4.cs.princeton.edu/code/algs4.jar\">algs4.jar</a> instead.\n\n<br>\n\n## Design goals\n\nOur original goal was to cover the <em>50 algorithms that every programmer should know</em>.\nWe use the word <em>programmer</em> to refer to anyone engaged in trying to accomplish\nsomething with the help of a computer, including scientists, engineers, and applications\ndevelopers, not to mention college students in science, engineering, and computer science.\nThe code is optimized for clarity, portability, and efficiency. While some of our \nimplementations are as fast as (or faster than) their counterparts in <tt>java.util</tt>,\nour main goal is to express the core algorithmic ideas in an elegant and simple manner.\nWhile we embrace some advanced Java features (such as generics and iterators),\nwe avoid those that interfere with the exposition (such as inheritance and concurrency).\n\n## Build managers\n\nThis repository is intended for use with either the <a href = \"https://maven.apache.org\">Maven</a>\nor <a href = \"https://gradle.org\">Gradle</a> build managers.\nIt can be run from either the command line or integrated into\nEclipse, NetBeans, and IntelliJ.\nYou can also access it via <a href = \"https://bintray.com/algs4/maven/algs4\">Bintray</a>.\n\n## Coursera Algorithms, Part I and II students\n\nFeel free to use this public repository to develop solutions to the programming assignments.\nHowever, please do not store solutions to programming assignments in public repositories.\n\n\n## Copyright\n\nCopyright &copy; 2000&ndash;2023 by Robert Sedgewick and Kevin Wayne.\n\n## License\n\nThis code is released under GPLv3.\n\n## Contribute to this repository\n\nThis <a href = \"http://algs4.cs.princeton.edu/code/wishlist.txt\">wishlist.txt</a>\ncontains a list of algorithms and data structures that we would\nlike to add to the repository. Indeed, several of the algorithms and\ndata structures in this repository were contributed by others. If interested, please\nfollow the same style as the code in the repository and thoroughly test your\ncode before contacting us.\n\n## Support for other programming languages\n\nSome of the code in this repository has been translated to other languages:\n<ul>\n<li><a href = \"https://github.com/garyaiki/Scala-Algorithms\">Scala</a> by Gary Struthers\n<li><a href = \"https://github.com/nguyenqthai/Algs4Net\">.NET</a> by Quoc Thai\n<li><a href = \"https://github.com/itu-algorithms/itu.algs4\">Python</a> by ITU Copenhagen\n<li><a href = \"https://github.com/shellfly/algs4-py\">Python</a> by Li Hao\n<li><a href = \"https://github.com/shellfly/algo\">Go</a> by Li Hao\n</ul>\n\n\n## Credits\n\nThanks to Peter Korgan for Maven and Gradle support.\n"
  },
  {
    "path": "USING-MAVEN.md",
    "content": "This file provides brief instructions on how to add this repository to\na Maven build, from Eclipse, NetBeans, IntelliJ, or the command line.\nSpecifically, it provides instructions on creating a version of algs4.jar\nthat you can use as a dependency in your projects.\n\nThese instructions assume that you already have installed Java 7\n(JDK 1.7) or above.\n\n\nUsing Maven in Eclipse for Java Developers\n------------------------------------------\nIf m2e (Maven plugin) is not built into Eclipse, follow these steps to install the plugin:\n\n  * Open Eclipse.\n  * Go to Help -> Eclipse Marketplace.\n  * Search for Maven.\n  * Click \"Install\" button at \"Maven Integration for Eclipse\" or \"m2e\" section.\n  * Follow the instruction step by step.,\n\nRestart Eclipse after installing m2e.\n\nNow you can import algs4 as \"Maven Project\" into Eclipse:\n\n  * Open menu: File-> Import-> Maven-> Existing Maven Projects...\n  * Choose directory of algs4.\n  * Confirm import.\n\nTo complete dependencies resolution after import:\n  * Right click on the project, choose Maven -> Update Project...\n  * Confirm project update.\n\nTo build project in Eclipse:\nEclipse automatically builds the project every time it saved.\nBut if you want enforce build, do following:\n  * Right click on the project in Eclipse.\n  * Choose Run as... Maven build.\n\nMaven will put algs4-<version>.jar in the directory <algs4 directory>/target.\nYou can use this jar as a dependency in your projects.\n\n\nUsing Maven in IntelliJ IDEA\n----------------------------\nImport algs4 as \"Maven Project\" into IntelliJ IDEA:\n\n1. Open menu: File -> New -> Module from Existing Sources...\n2. Choose directory of algs4.\n3. Choose Import module from external model - Maven.\n4. Finish.\n\nLast, edit `pom.xml` to add dependency:\n```xml\n<dependency>\n    <groupId>edu.princeton.cs</groupId>\n    <artifactId>algs4</artifactId>\n    <version>1.0.0.0</version>\n</dependency>\n```\n\nUsing Maven in Netbeans\n-----------------------\n\n\nUsing Maven from the Windows Command Prompt\n-------------------------------------------\nDownload and install Maven by following the instructions at\nhttps://maven.apache.org.\n\nLocate the installation directory for Maven, e.g., C:\\<apache-maven-x-y-z>\n\nLocate the installation directory for Java, e.g., C:\\Program Files\\Java\\<JDK-x-y-z>\n\nSet the following environment variables:\n\nset JAVA_HOME=C:\\Program Files\\Java\\<JDK-x-y-z>\nset PATH=%JAVA_HOME%\\bin;%PATH%\nset M2_HOME=C:\\<apache-maven-x-y-z>\nset PATH=%M2_HOME%\\bin;%PATH%\n\nTo create the algs4-<version>.jar package and install it in the local\nrepository for reuse from other projects, change to the directory of\nthe algs4 repository and run Maven.\n\ncd <algs4 directory>\nmvn clean install\n\nMaven will put algs4-<version>.jar in the directory <algs4 directory>/target.\nYou can use this jar as a dependency in your projects.\n\n\n\nUsing Maven from the Linux / Mac OS X bash shell\n------------------------------------------------\nDownload and install Maven, either by using your favorite package\nmanager  (such as apt-get) or by following the instructions at\nhttps://maven.apache.org.\n\nLocate the installation directory for Maven, e.g., /my/maven/<apache-maven-x-y-z>\n\nLocate the installation directory for Java, e.g., /my/java/<JDK-x-y-z->\n\nSet the following environment variables:\n\nexport JAVA_HOME=/my/java/<JDK-x-y-z>\nexport PATH=$JAVA_HOME/bin:$PATH\nexport M2_HOME=/my/maven/<apache-maven-x-y-z>\nexport PATH=$M2_HOME/bin:$PATH\n\nTo create the algs4-<version>.jar package and install it in the local\nrepository for reuse from other projects, change to the directory of\nthe algs4 repository and run Maven.\n\ncd <algs4 directory>\nmvn clean install\n\nMaven will put algs4-<version>.jar in the directory <algs4 directory>/target.\nYou can use this jar as a dependency in your projects.\n\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n  repositories {\n        jcenter()\n   }\n}\n\nplugins {\n    id \"com.jfrog.bintray\" version \"1.7\"\n}\n\ngroup = 'edu.princeton.cs'\nversion = '1.0.1'\n\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n    apply plugin: 'java'\n    apply plugin: 'eclipse'\n    apply plugin: 'idea'\n    apply plugin: 'maven-publish'\n\n    sourceCompatibility = 1.7\n    targetCompatibility = 1.7\n}\n\ntask sourcesJar(type: Jar, dependsOn:classes) {\n    classifier = 'sources'\n    from sourceSets.main.allSource\n}\n\ntask javadocJar(type: Jar) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\n\nartifacts {\n    archives sourcesJar\n    archives javadocJar\n}\n\npublishing {\n    publications {\n        MyPublication(MavenPublication) {\n            from components.java\n            artifact sourcesJar\n            artifact javadocJar\n            groupId 'edu.princeton.cs'\n                    artifactId 'algs4'\n                    version '1.0.2'\n        }\n    }\n}\n\nbintray {\n    user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')\n    key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')\n    publications = ['MyPublication']\n    publish = true\n    override = false\n    pkg {\n        repo = 'maven'\n        name = 'algs4'\n        userOrg = 'algs4'\n        desc = 'Source Code for Algorithms, 4th Edition'\n        licenses = ['GPL-3.0']\n        vcsUrl = 'https://github.com/kevin-wayne/algs4.git'\n        websiteUrl = 'https://github.com/kevin-wayne/algs4'\n        labels = ['algorithms', 'java', 'Robert Sedgewick', 'Kevin Wayne']\n        publicDownloadNumbers = true\n        githubRepo = 'kevin-wayne/algs4'\n        githubReleaseNotesFile = 'README.md'\n        version {\n            name = '1.0.2'\n            vcsTag = '1.0.2'\n        }\n    }\n}\n\nwrapper {\n  gradleVersion = '2.6'\n}"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>edu.princeton.cs</groupId>\n\t<artifactId>algs4</artifactId>\n\t<packaging>jar</packaging>\n\t<version>1.0.0.0</version>\n\t<name>algs4</name>\n\t<licenses>\n\t\t<license>\n\t\t\t<name>GNU GENERAL PUBLIC LICENSE</name>\n\t\t\t<url>http://www.gnu.org/licenses/gpl-3.0.en.html</url>\n\t\t</license>\n\t</licenses>\n\t<developers>\n\t\t<developer>\n\t\t\t<id>kevin</id>\n\t\t\t<name>Kevin Wayne</name>\n\t\t\t<email>wayne@CS.Princeton.EDU</email>\n\t\t\t<url>https://www.cs.princeton.edu/~wayne/contact/</url>\n\t\t\t<organization>Princeton University </organization>\n\t\t\t<organizationUrl>https://www.cs.princeton.edu</organizationUrl>\n\t\t\t<roles>\n\t\t\t\t<role>author</role>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t\t<timezone>UTC/GMT -4:00 hours</timezone>\n\t\t\t<properties>\n\t\t\t\t<picUrl>https://www.cs.princeton.edu/~wayne/contact/KevinWayne.jpg</picUrl>\n\t\t\t</properties>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>robert</id>\n\t\t\t<name>Robert Sedgewick</name>\n\t\t\t<roles>\n\t\t\t\t<role>author</role>\n\t\t\t</roles>\n\t\t</developer>\n\t</developers>\n\t<issueManagement>\n\t\t<system>github.com</system>\n\t\t<url>https://github.com/kevin-wayne/algs4/issues</url>\n\t</issueManagement>\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>main-build</id>\n\t\t\t\t<activation>\n\t\t\t\t\t<activeByDefault>true</activeByDefault>\n\t\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t\t\t<java.version>1.8</java.version>\n\t\t\t</properties>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t\t\t<version>3.3</version>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<source>${java.version}</source>\n\t\t\t\t\t\t\t<target>${java.version}</target>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</plugin>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t\t\t<version>3.0.1</version>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<id>attach-sources</id>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t\t<repositories>\n\t\t\t</repositories>\n\t\t</profile>\n\t</profiles>\n\t<dependencies>\n\t</dependencies>  \n</project>\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AVLTreeST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AVLTreeST.java\n *  Execution:    java AVLTreeST < input.txt\n *  Dependencies: StdIn.java StdOut.java  \n *  Data files:   https://algs4.cs.princeton.edu/33balanced/tinyST.txt  \n *    \n *  A symbol table implemented using an AVL tree.\n *\n *  % more tinyST.txt\n *  S E A R C H E X A M P L E\n *  \n *  % java AVLTreeST < tinyST.txt\n *  A 8\n *  C 4\n *  E 12\n *  H 5\n *  L 11\n *  M 9\n *  P 10\n *  R 3\n *  S 0\n *  X 7\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code AVLTreeST} class represents an ordered symbol table of\n *  generic key-value pairs. It supports the usual <em>put</em>, <em>get</em>,\n *  <em>contains</em>, <em>delete</em>, <em>size</em>, and <em>is-empty</em>\n *  methods. It also provides ordered methods for finding the <em>minimum</em>,\n *  <em>maximum</em>, <em>floor</em>, and <em>ceiling</em>. It also provides a\n *  <em>keys</em> method for iterating over all of the keys. A symbol table\n *  implements the <em>associative array</em> abstraction: when associating a\n *  value with a key that is already in the symbol table, the convention is to\n *  replace the old value with the new value. Unlike {@link java.util.Map}, this\n *  class uses the convention that values cannot be {@code null}\n *  —setting the value associated with a key to {@code null} is\n *  equivalent to deleting the key from the symbol table.\n *  <p>\n *  This symbol table implementation uses internally an\n *  <a href=\"https://en.wikipedia.org/wiki/AVL_tree\"> AVL tree </a> (Georgy\n *  Adelson-Velsky and Evgenii Landis' tree) which is a self-balancing BST.\n *  In an AVL tree, the heights of the two child subtrees of any\n *  node differ by at most one; if at any time they differ by more than one,\n *  rebalancing is done to restore this property.\n *  <p>\n *  This implementation requires that the key type implements the\n *  {@code Comparable} interface and calls the {@code compareTo()} and\n *  method to compare two keys. It does not call either {@code equals()} or\n *  {@code hashCode()}. The <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>minimum</em>, <em>maximum</em>, <em>ceiling</em>, and\n *  <em>floor</em> operations each take logarithmic time in the worst case. The\n *  <em>size</em>, and <em>is-empty</em> operations take constant time.\n *  Construction also takes constant time.\n * \n *  For other implementations of the same API, see {@link ST}, {@link BinarySearchST},\n *  {@link SequentialSearchST}, {@link BST}, {@link RedBlackBST},\n *  {@link SeparateChainingHashST}, and {@link LinearProbingHashST}.\n * \n *  @author Marcelo Silva\n */\n\npublic class AVLTreeST<Key extends Comparable<Key>, Value> {\n\n    /**\n     * The root node.\n     */\n    private Node root;\n\n    /**\n     * This class represents an inner node of the AVL tree.\n     */\n    private class Node {\n        private final Key key;   // the key\n        private Value val;       // the associated value\n        private int height;      // height of the subtree\n        private int size;        // number of nodes in subtree\n        private Node left;       // left subtree\n        private Node right;      // right subtree\n\n        public Node(Key key, Value val, int height, int size) {\n            this.key = key;\n            this.val = val;\n            this.size = size;\n            this.height = height;\n        }\n    }\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public AVLTreeST() {\n    }\n\n    /**\n     * Checks if the symbol table is empty.\n     * \n     * @return {@code true} if the symbol table is empty.\n     */\n    public boolean isEmpty() {\n        return root == null;\n    }\n\n    /**\n     * Returns the number key-value pairs in the symbol table.\n     * \n     * @return the number key-value pairs in the symbol table\n     */\n    public int size() {\n        return size(root);\n    }\n\n    /**\n     * Returns the number of nodes in the subtree.\n     * \n     * @param x the subtree\n     * \n     * @return the number of nodes in the subtree\n     */\n    private int size(Node x) {\n        if (x == null) return 0;\n        return x.size;\n    }\n\n    /**\n     * Returns the height of the internal AVL tree. It is assumed that the\n     * height of an empty tree is -1 and the height of a tree with just one node\n     * is 0.\n     * \n     * @return the height of the internal AVL tree\n     */\n    public int height() {\n        return height(root);\n    }\n\n    /**\n     * Returns the height of the subtree.\n     * \n     * @param x the subtree\n     * \n     * @return the height of the subtree.\n     */\n    private int height(Node x) {\n        if (x == null) return -1;\n        return x.height;\n    }\n\n    /**\n     * Returns the value associated with the given key.\n     * \n     * @param key the key\n     * @return the value associated with the given key if the key is in the\n     *         symbol table and {@code null} if the key is not in the\n     *         symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        Node x = get(root, key);\n        if (x == null) return null;\n        return x.val;\n    }\n\n    /**\n     * Returns value associated with the given key in the subtree or\n     * {@code null} if no such key.\n     * \n     * @param x the subtree\n     * @param key the key\n     * @return value associated with the given key in the subtree or\n     *         {@code null} if no such key\n     */\n    private Node get(Node x, Key key) {\n        if (x == null) return null;\n        int cmp = key.compareTo(x.key);\n        if (cmp < 0) return get(x.left, key);\n        else if (cmp > 0) return get(x.right, key);\n        else return x;\n    }\n\n    /**\n     * Checks if the symbol table contains the given key.\n     * \n     * @param key the key\n     * @return {@code true} if the symbol table contains {@code key}\n     *         and {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        return get(key) != null;\n    }\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting\n     * the old value with the new value if the symbol table already contains the\n     * specified key. Deletes the specified key (and its associated value) from\n     * this symbol table if the specified value is {@code null}.\n     * \n     * @param key the key\n     * @param val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n        if (val == null) {\n            delete(key);\n            return;\n        }\n        root = put(root, key, val);\n        assert check();\n    }\n\n    /**\n     * Inserts the key-value pair in the subtree. It overrides the old value\n     * with the new value if the symbol table already contains the specified key\n     * and deletes the specified key (and its associated value) from this symbol\n     * table if the specified value is {@code null}.\n     * \n     * @param x the subtree\n     * @param key the key\n     * @param val the value\n     * @return the subtree\n     */\n    private Node put(Node x, Key key, Value val) {\n        if (x == null) return new Node(key, val, 0, 1);\n        int cmp = key.compareTo(x.key);\n        if (cmp < 0) {\n            x.left = put(x.left, key, val);\n        }\n        else if (cmp > 0) {\n            x.right = put(x.right, key, val);\n        }\n        else {\n            x.val = val;\n            return x;\n        }\n        x.size = 1 + size(x.left) + size(x.right);\n        x.height = 1 + Math.max(height(x.left), height(x.right));\n        return balance(x);\n    }\n\n    /**\n     * Restores the AVL tree property of the subtree.\n     * \n     * @param x the subtree\n     * @return the subtree with restored AVL property\n     */\n    private Node balance(Node x) {\n        if (balanceFactor(x) < -1) {\n            if (balanceFactor(x.right) > 0) {\n                x.right = rotateRight(x.right);\n            }\n            x = rotateLeft(x);\n        }\n        else if (balanceFactor(x) > 1) {\n            if (balanceFactor(x.left) < 0) {\n                x.left = rotateLeft(x.left);\n            }\n            x = rotateRight(x);\n        }\n        return x;\n    }\n\n    /**\n     * Returns the balance factor of the subtree. The balance factor is defined\n     * as the difference in height of the left subtree and right subtree, in\n     * this order. Therefore, a subtree with a balance factor of -1, 0 or 1 has\n     * the AVL property since the heights of the two child subtrees differ by at\n     * most one.\n     * \n     * @param x the subtree\n     * @return the balance factor of the subtree\n     */\n    private int balanceFactor(Node x) {\n        return height(x.left) - height(x.right);\n    }\n\n    /**\n     * Rotates the given subtree to the right.\n     * \n     * @param x the subtree\n     * @return the right rotated subtree\n     */\n    private Node rotateRight(Node x) {\n        Node y = x.left;\n        x.left = y.right;\n        y.right = x;\n        y.size = x.size;\n        x.size = 1 + size(x.left) + size(x.right);\n        x.height = 1 + Math.max(height(x.left), height(x.right));\n        y.height = 1 + Math.max(height(y.left), height(y.right));\n        return y;\n    }\n\n    /**\n     * Rotates the given subtree to the left.\n     * \n     * @param x the subtree\n     * @return the left rotated subtree\n     */\n    private Node rotateLeft(Node x) {\n        Node y = x.right;\n        x.right = y.left;\n        y.left = x;\n        y.size = x.size;\n        x.size = 1 + size(x.left) + size(x.right);\n        x.height = 1 + Math.max(height(x.left), height(x.right));\n        y.height = 1 + Math.max(height(y.left), height(y.right));\n        return y;\n    }\n\n    /**\n     * Removes the specified key and its associated value from the symbol table\n     * (if the key is in the symbol table).\n     * \n     * @param key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        if (!contains(key)) return;\n        root = delete(root, key);\n        assert check();\n    }\n\n    /**\n     * Removes the specified key and its associated value from the given\n     * subtree.\n     * \n     * @param x the subtree\n     * @param key the key\n     * @return the updated subtree\n     */\n    private Node delete(Node x, Key key) {\n        int cmp = key.compareTo(x.key);\n        if (cmp < 0) {\n            x.left = delete(x.left, key);\n        }\n        else if (cmp > 0) {\n            x.right = delete(x.right, key);\n        }\n        else {\n            if (x.left == null) {\n                return x.right;\n            }\n            else if (x.right == null) {\n                return x.left;\n            }\n            else {\n                Node y = x;\n                x = min(y.right);\n                x.right = deleteMin(y.right);\n                x.left = y.left;\n            }\n        }\n        x.size = 1 + size(x.left) + size(x.right);\n        x.height = 1 + Math.max(height(x.left), height(x.right));\n        return balance(x);\n    }\n\n    /**\n     * Removes the smallest key and associated value from the symbol table.\n     * \n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMin() {\n        if (isEmpty()) throw new NoSuchElementException(\"called deleteMin() with empty symbol table\");\n        root = deleteMin(root);\n        assert check();\n    }\n\n    /**\n     * Removes the smallest key and associated value from the given subtree.\n     * \n     * @param x the subtree\n     * @return the updated subtree\n     */\n    private Node deleteMin(Node x) {\n        if (x.left == null) return x.right;\n        x.left = deleteMin(x.left);\n        x.size = 1 + size(x.left) + size(x.right);\n        x.height = 1 + Math.max(height(x.left), height(x.right));\n        return balance(x);\n    }\n\n    /**\n     * Removes the largest key and associated value from the symbol table.\n     * \n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMax() {\n        if (isEmpty()) throw new NoSuchElementException(\"called deleteMax() with empty symbol table\");\n        root = deleteMax(root);\n        assert check();\n    }\n\n    /**\n     * Removes the largest key and associated value from the given subtree.\n     * \n     * @param x the subtree\n     * @return the updated subtree\n     */\n    private Node deleteMax(Node x) {\n        if (x.right == null) return x.left;\n        x.right = deleteMax(x.right);\n        x.size = 1 + size(x.left) + size(x.right);\n        x.height = 1 + Math.max(height(x.left), height(x.right));\n        return balance(x);\n    }\n\n    /**\n     * Returns the smallest key in the symbol table.\n     * \n     * @return the smallest key in the symbol table\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"called min() with empty symbol table\");\n        return min(root).key;\n    }\n\n    /**\n     * Returns the node with the smallest key in the subtree.\n     * \n     * @param x the subtree\n     * @return the node with the smallest key in the subtree\n     */\n    private Node min(Node x) {\n        if (x.left == null) return x;\n        return min(x.left);\n    }\n\n    /**\n     * Returns the largest key in the symbol table.\n     * \n     * @return the largest key in the symbol table\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"called max() with empty symbol table\");\n        return max(root).key;\n    }\n\n    /**\n     * Returns the node with the largest key in the subtree.\n     * \n     * @param x the subtree\n     * @return the node with the largest key in the subtree\n     */\n    private Node max(Node x) {\n        if (x.right == null) return x;\n        return max(x.right);\n    }\n\n    /**\n     * Returns the largest key in the symbol table less than or equal to\n     * {@code key}.\n     * \n     * @param key the key\n     * @return the largest key in the symbol table less than or equal to\n     *         {@code key}\n     * @throws NoSuchElementException if the symbol table is empty\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key floor(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to floor() is null\");\n        if (isEmpty()) throw new NoSuchElementException(\"called floor() with empty symbol table\");\n        Node x = floor(root, key);\n        if (x == null) return null;\n        else return x.key;\n    }\n\n    /**\n     * Returns the node in the subtree with the largest key less than or equal\n     * to the given key.\n     * \n     * @param x the subtree\n     * @param key the key\n     * @return the node in the subtree with the largest key less than or equal\n     *         to the given key\n     */\n    private Node floor(Node x, Key key) {\n        if (x == null) return null;\n        int cmp = key.compareTo(x.key);\n        if (cmp == 0) return x;\n        if (cmp < 0) return floor(x.left, key);\n        Node y = floor(x.right, key);\n        if (y != null) return y;\n        else return x;\n    }\n\n    /**\n     * Returns the smallest key in the symbol table greater than or equal to\n     * {@code key}.\n     * \n     * @param key the key\n     * @return the smallest key in the symbol table greater than or equal to\n     *         {@code key}\n     * @throws NoSuchElementException if the symbol table is empty\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key ceiling(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to ceiling() is null\");\n        if (isEmpty()) throw new NoSuchElementException(\"called ceiling() with empty symbol table\");\n        Node x = ceiling(root, key);\n        if (x == null) return null;\n        else return x.key;\n    }\n\n    /**\n     * Returns the node in the subtree with the smallest key greater than or\n     * equal to the given key.\n     * \n     * @param x the subtree\n     * @param key the key\n     * @return the node in the subtree with the smallest key greater than or\n     *         equal to the given key\n     */\n    private Node ceiling(Node x, Key key) {\n        if (x == null) return null;\n        int cmp = key.compareTo(x.key);\n        if (cmp == 0) return x;\n        if (cmp > 0) return ceiling(x.right, key);\n        Node y = ceiling(x.left, key);\n        if (y != null) return y;\n        else return x;\n    }\n\n    /**\n     * Returns the kth smallest key in the symbol table.\n     * \n     * @param k the order statistic\n     * @return the kth smallest key in the symbol table\n     * @throws IllegalArgumentException unless {@code k} is between 0 and\n     *             {@code size() -1 }\n     */\n    public Key select(int k) {\n        if (k < 0 || k >= size()) throw new IllegalArgumentException(\"k is not in range 0-\" + (size() - 1));\n        Node x = select(root, k);\n        return x.key;\n    }\n\n    /**\n     * Returns the node with key the kth smallest key in the subtree.\n     * \n     * @param x the subtree\n     * @param k the kth smallest key in the subtree\n     * @return the node with key the kth smallest key in the subtree\n     */\n    private Node select(Node x, int k) {\n        if (x == null) return null;\n        int t = size(x.left);\n        if (t > k) return select(x.left, k);\n        else if (t < k) return select(x.right, k - t - 1);\n        else return x;\n    }\n\n    /**\n     * Returns the number of keys in the symbol table strictly less than\n     * {@code key}.\n     * \n     * @param key the key\n     * @return the number of keys in the symbol table strictly less than\n     *         {@code key}\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public int rank(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to rank() is null\");\n        return rank(key, root);\n    }\n\n    /**\n     * Returns the number of keys in the subtree less than key.\n     * \n     * @param key the key\n     * @param x the subtree\n     * @return the number of keys in the subtree less than key\n     */\n    private int rank(Key key, Node x) {\n        if (x == null) return 0;\n        int cmp = key.compareTo(x.key);\n        if (cmp < 0) return rank(key, x.left);\n        else if (cmp > 0) return 1 + size(x.left) + rank(key, x.right);\n        else return size(x.left);\n    }\n\n    /**\n     * Returns all keys in the symbol table.\n     * \n     * @return all keys in the symbol table\n     */\n    public Iterable<Key> keys() {\n        return keysInOrder();\n    }\n\n    /**\n     * Returns all keys in the symbol table following an in-order traversal.\n     * \n     * @return all keys in the symbol table following an in-order traversal\n     */\n    public Iterable<Key> keysInOrder() {\n        Queue<Key> queue = new Queue<Key>();\n        keysInOrder(root, queue);\n        return queue;\n    }\n\n    /**\n     * Adds the keys in the subtree to queue following an in-order traversal.\n     * \n     * @param x the subtree\n     * @param queue the queue\n     */\n    private void keysInOrder(Node x, Queue<Key> queue) {\n        if (x == null) return;\n        keysInOrder(x.left, queue);\n        queue.enqueue(x.key);\n        keysInOrder(x.right, queue);\n    }\n\n    /**\n     * Returns all keys in the symbol table following a level-order traversal.\n     * \n     * @return all keys in the symbol table following a level-order traversal.\n     */\n    public Iterable<Key> keysLevelOrder() {\n        Queue<Key> queue = new Queue<Key>();\n        if (!isEmpty()) {\n            Queue<Node> queue2 = new Queue<Node>();\n            queue2.enqueue(root);\n            while (!queue2.isEmpty()) {\n                Node x = queue2.dequeue();\n                queue.enqueue(x.key);\n                if (x.left != null) {\n                    queue2.enqueue(x.left);\n                }\n                if (x.right != null) {\n                    queue2.enqueue(x.right);\n                }\n            }\n        }\n        return queue;\n    }\n\n    /**\n     * Returns all keys in the symbol table in the given range.\n     * \n     * @param lo the lowest key\n     * @param hi the highest key\n     * @return all keys in the symbol table between {@code lo} (inclusive)\n     *         and {@code hi} (exclusive)\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *             is {@code null}\n     */\n    public Iterable<Key> keys(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to keys() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to keys() is null\");\n        Queue<Key> queue = new Queue<Key>();\n        keys(root, queue, lo, hi);\n        return queue;\n    }\n\n    /**\n     * Adds the keys between {@code lo} and {@code hi} in the subtree\n     * to the {@code queue}.\n     * \n     * @param x the subtree\n     * @param queue the queue\n     * @param lo the lowest key\n     * @param hi the highest key\n     */\n    private void keys(Node x, Queue<Key> queue, Key lo, Key hi) {\n        if (x == null) return;\n        int cmplo = lo.compareTo(x.key);\n        int cmphi = hi.compareTo(x.key);\n        if (cmplo < 0) keys(x.left, queue, lo, hi);\n        if (cmplo <= 0 && cmphi >= 0) queue.enqueue(x.key);\n        if (cmphi > 0) keys(x.right, queue, lo, hi);\n    }\n\n    /**\n     * Returns the number of keys in the symbol table in the given range.\n     * \n     * @param lo minimum endpoint\n     * @param hi maximum endpoint\n     * @return the number of keys in the symbol table between {@code lo}\n     *         (inclusive) and {@code hi} (exclusive)\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *             is {@code null}\n     */\n    public int size(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to size() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to size() is null\");\n        if (lo.compareTo(hi) > 0) return 0;\n        if (contains(hi)) return rank(hi) - rank(lo) + 1;\n        else return rank(hi) - rank(lo);\n    }\n\n    /**\n     * Checks if the AVL tree invariants are fine.\n     * \n     * @return {@code true} if the AVL tree invariants are fine\n     */\n    private boolean check() {\n        if (!isBST()) StdOut.println(\"Symmetric order not consistent\");\n        if (!isAVL()) StdOut.println(\"AVL property not consistent\");\n        if (!isSizeConsistent()) StdOut.println(\"Subtree counts not consistent\");\n        if (!isRankConsistent()) StdOut.println(\"Ranks not consistent\");\n        return isBST() && isAVL() && isSizeConsistent() && isRankConsistent();\n    }\n\n    /**\n     * Checks if AVL property is consistent.\n     * \n     * @return {@code true} if AVL property is consistent.\n     */\n    private boolean isAVL() {\n        return isAVL(root);\n    }\n\n    /**\n     * Checks if AVL property is consistent in the subtree.\n     * \n     * @param x the subtree\n     * @return {@code true} if AVL property is consistent in the subtree\n     */\n    private boolean isAVL(Node x) {\n        if (x == null) return true;\n        int bf = balanceFactor(x);\n        if (bf > 1 || bf < -1) return false;\n        return isAVL(x.left) && isAVL(x.right);\n    }\n\n    /**\n     * Checks if the symmetric order is consistent.\n     * \n     * @return {@code true} if the symmetric order is consistent\n     */\n    private boolean isBST() {\n        return isBST(root, null, null);\n    }\n\n    /**\n     * Checks if the tree rooted at x is a BST with all keys strictly between\n     * min and max (if min or max is null, treat as empty constraint) Credit:\n     * Bob Dondero's elegant solution\n     * \n     * @param x the subtree\n     * @param min the minimum key in subtree\n     * @param max the maximum key in subtree\n     * @return {@code true} if if the symmetric order is consistent\n     */\n    private boolean isBST(Node x, Key min, Key max) {\n        if (x == null) return true;\n        if (min != null && x.key.compareTo(min) <= 0) return false;\n        if (max != null && x.key.compareTo(max) >= 0) return false;\n        return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);\n    }\n\n    /**\n     * Checks if size is consistent.\n     * \n     * @return {@code true} if size is consistent\n     */\n    private boolean isSizeConsistent() {\n        return isSizeConsistent(root);\n    }\n\n    /**\n     * Checks if the size of the subtree is consistent.\n     * \n     * @return {@code true} if the size of the subtree is consistent\n     */\n    private boolean isSizeConsistent(Node x) {\n        if (x == null) return true;\n        if (x.size != size(x.left) + size(x.right) + 1) return false;\n        return isSizeConsistent(x.left) && isSizeConsistent(x.right);\n    }\n\n    /**\n     * Checks if rank is consistent.\n     * \n     * @return {@code true} if rank is consistent\n     */\n    private boolean isRankConsistent() {\n        for (int i = 0; i < size(); i++)\n            if (i != rank(select(i))) return false;\n        for (Key key : keys())\n            if (key.compareTo(select(rank(key))) != 0) return false;\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code AVLTreeST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        AVLTreeST<String, Integer> st = new AVLTreeST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n        StdOut.println();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Accumulator.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Accumulator.java\n *  Execution:    java Accumulator < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *\n *  Mutable data type that calculates the mean, sample standard\n *  deviation, and sample variance of a stream of real numbers\n *  use a stable, one-pass algorithm.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code Accumulator} class is a data type for computing the running\n *  mean, sample standard deviation, and sample variance of a stream of real\n *  numbers. It provides an example of a mutable data type and a streaming\n *  algorithm.\n *  <p>\n *  This implementation uses a one-pass algorithm that is less susceptible\n *  to floating-point roundoff error than the more straightforward\n *  implementation based on saving the sum of the squares of the numbers.\n *  This technique is due to\n *  <a href = \"https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm\">B. P. Welford</a>.\n *  Each operation takes constant time in the worst case.\n *  The amount of memory is constant - the data values are not stored.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Accumulator {\n    private int n = 0;          // number of data values\n    private double sum = 0.0;   // sample variance * (n-1)\n    private double mu = 0.0;    // sample mean\n\n    /**\n     * Initializes an accumulator.\n     */\n    public Accumulator() {\n    }\n\n    /**\n     * Adds the specified data value to the accumulator.\n     * @param  x the data value\n     */\n    public void addDataValue(double x) {\n        n++;\n        double delta = x - mu;\n        mu  += delta / n;\n        sum += ((double) (n - 1) / n) * delta * delta;\n    }\n\n    /**\n     * Returns the mean of the data values.\n     * @return the mean of the data values\n     */\n    public double mean() {\n        return mu;\n    }\n\n    /**\n     * Returns the sample variance of the data values.\n     * @return the sample variance of the data values\n     */\n    public double var() {\n        if (n <= 1) return Double.NaN;\n        return sum / (n - 1);\n    }\n\n    /**\n     * Returns the sample standard deviation of the data values.\n     * @return the sample standard deviation of the data values\n     */\n    public double stddev() {\n        return Math.sqrt(this.var());\n    }\n\n    /**\n     * Returns the number of data values.\n     * @return the number of data values\n     */\n    public int count() {\n        return n;\n    }\n\n    /**\n     * Returns a string representation of this accumulator.\n     * @return a string representation of this accumulator\n     */\n    public String toString() {\n        return \"n = \" + n + \", mean = \" + mean() + \", stddev = \" + stddev();\n    }\n\n    /**\n     * Unit tests the {@code Accumulator} data type.\n     * Reads in a stream of real number from standard input;\n     * adds them to the accumulator; and prints the mean,\n     * sample standard deviation, and sample variance to standard\n     * output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Accumulator stats = new Accumulator();\n        while (!StdIn.isEmpty()) {\n            double x = StdIn.readDouble();\n            stats.addDataValue(x);\n        }\n\n        StdOut.printf(\"n      = %d\\n\",   stats.count());\n        StdOut.printf(\"mean   = %.5f\\n\", stats.mean());\n        StdOut.printf(\"stddev = %.5f\\n\", stats.stddev());\n        StdOut.printf(\"var    = %.5f\\n\", stats.var());\n        StdOut.println(stats);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AcyclicLP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AcyclicLP.java\n *  Execution:    java AcyclicP V E\n *  Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Topological.java\n *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWDAG.txt\n *\n *  Computes longest paths in an edge-weighted acyclic digraph.\n *\n *  Remark: should probably check that graph is a DAG before running\n *\n *  % java AcyclicLP tinyEWDAG.txt 5\n *  5 to 0 (2.44)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93   4->0  0.38\n *  5 to 1 (0.32)  5->1  0.32\n *  5 to 2 (2.77)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93   4->7  0.37   7->2  0.34\n *  5 to 3 (0.61)  5->1  0.32   1->3  0.29\n *  5 to 4 (2.06)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93\n *  5 to 5 (0.00)\n *  5 to 6 (1.13)  5->1  0.32   1->3  0.29   3->6  0.52\n *  5 to 7 (2.43)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93   4->7  0.37\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code AcyclicLP} class represents a data type for solving the\n *  single-source longest paths problem in edge-weighted directed\n *  acyclic graphs (DAGs). The edge weights can be positive, negative, or zero.\n *  <p>\n *  This implementation uses a topological-sort based algorithm.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted digraph).\n *  <p>\n *  This correctly computes longest paths if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>. Since all intermediate\n *  results are sums of edge weights, they are bounded by <em>V C</em>,\n *  where <em>V</em> is the number of vertices and <em>C</em> is the maximum\n *  absolute value of any edge weight.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class AcyclicLP {\n    private double[] distTo;          // distTo[v] = distance  of longest s->v path\n    private DirectedEdge[] edgeTo;    // edgeTo[v] = last edge on longest s->v path\n\n    /**\n     * Computes a longest paths tree from {@code s} to every other vertex in\n     * the directed acyclic graph {@code digraph}.\n     * @param digraph the acyclic digraph\n     * @param s the source vertex\n     * @throws IllegalArgumentException if the digraph is not acyclic\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public AcyclicLP(EdgeWeightedDigraph digraph, int s) {\n        distTo = new double[digraph.V()];\n        edgeTo = new DirectedEdge[digraph.V()];\n\n        validateVertex(s);\n\n        for (int v = 0; v < digraph.V(); v++)\n            distTo[v] = Double.NEGATIVE_INFINITY;\n        distTo[s] = 0.0;\n\n        // relax vertices in topological order\n        Topological topological = new Topological(digraph);\n        if (!topological.hasOrder())\n            throw new IllegalArgumentException(\"Digraph is not acyclic.\");\n        for (int v : topological.order()) {\n            for (DirectedEdge e : digraph.adj(v))\n                relax(e);\n        }\n    }\n\n    // relax edge e, but update if you find a *longer* path\n    private void relax(DirectedEdge e) {\n        int v = e.from(), w = e.to();\n        if (distTo[w] < distTo[v] + e.weight()) {\n            distTo[w] = distTo[v] + e.weight();\n            edgeTo[w] = e;\n        }\n    }\n\n    /**\n     * Returns the length of a longest path from the source vertex {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return the length of a longest path from the source vertex {@code s} to vertex {@code v};\n     *         {@code Double.NEGATIVE_INFINITY} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public double distTo(int v) {\n        validateVertex(v);\n        return distTo[v];\n    }\n\n    /**\n     * Is there a path from the source vertex {@code s} to vertex {@code v}?\n     * @param  v the destination vertex\n     * @return {@code true} if there is a path from the source vertex\n     *         {@code s} to vertex {@code v}, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return distTo[v] > Double.NEGATIVE_INFINITY;\n    }\n\n    /**\n     * Returns a longest path from the source vertex {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return a longest path from the source vertex {@code s} to vertex {@code v}\n     *         as an iterable of edges, and {@code null} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<DirectedEdge> path = new Stack<DirectedEdge>();\n        for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {\n            path.push(e);\n        }\n        return path;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = distTo.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code AcyclicLP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        int s = Integer.parseInt(args[1]);\n        EdgeWeightedDigraph digraph = new EdgeWeightedDigraph(in);\n\n        AcyclicLP lp = new AcyclicLP(digraph, s);\n\n        for (int v = 0; v < digraph.V(); v++) {\n            if (lp.hasPathTo(v)) {\n                StdOut.printf(\"%d to %d (%.2f)  \", s, v, lp.distTo(v));\n                for (DirectedEdge e : lp.pathTo(v)) {\n                    StdOut.print(e + \"   \");\n                }\n                StdOut.println();\n            }\n            else {\n                StdOut.printf(\"%d to %d         no path\\n\", s, v);\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AcyclicSP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AcyclicSP.java\n *  Execution:    java AcyclicSP V E\n *  Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Topological.java\n *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWDAG.txt\n *\n *  Computes shortest paths in an edge-weighted acyclic digraph.\n *\n *  % java AcyclicSP tinyEWDAG.txt 5\n *  5 to 0 (0.73)  5->4  0.35   4->0  0.38\n *  5 to 1 (0.32)  5->1  0.32\n *  5 to 2 (0.62)  5->7  0.28   7->2  0.34\n *  5 to 3 (0.61)  5->1  0.32   1->3  0.29\n *  5 to 4 (0.35)  5->4  0.35\n *  5 to 5 (0.00)\n *  5 to 6 (1.13)  5->1  0.32   1->3  0.29   3->6  0.52\n *  5 to 7 (0.28)  5->7  0.28\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code AcyclicSP} class represents a data type for solving the\n *  single-source shortest paths problem in edge-weighted directed acyclic\n *  graphs (DAGs). The edge weights can be positive, negative, or zero.\n *  <p>\n *  This implementation uses a topological-sort based algorithm.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted digraph).\n *  <p>\n *  This correctly computes shortest paths if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>. Since all intermediate\n *  results are sums of edge weights, they are bounded by <em>V C</em>,\n *  where <em>V</em> is the number of vertices and <em>C</em> is the maximum\n *  absolute value of any edge weight.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class AcyclicSP {\n    private double[] distTo;         // distTo[v] = distance  of shortest s->v path\n    private DirectedEdge[] edgeTo;   // edgeTo[v] = last edge on shortest s->v path\n\n\n    /**\n     * Computes a shortest paths tree from {@code s} to every other vertex in\n     * the directed acyclic graph {@code digraph}.\n     * @param digraph the acyclic digraph\n     * @param s the source vertex\n     * @throws IllegalArgumentException if the digraph is not acyclic\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public AcyclicSP(EdgeWeightedDigraph digraph, int s) {\n        distTo = new double[digraph.V()];\n        edgeTo = new DirectedEdge[digraph.V()];\n\n        validateVertex(s);\n\n        for (int v = 0; v < digraph.V(); v++)\n            distTo[v] = Double.POSITIVE_INFINITY;\n        distTo[s] = 0.0;\n\n        // visit vertices in topological order\n        Topological topological = new Topological(digraph);\n        if (!topological.hasOrder())\n            throw new IllegalArgumentException(\"Digraph is not acyclic.\");\n        for (int v : topological.order()) {\n            for (DirectedEdge e : digraph.adj(v))\n                relax(e);\n        }\n    }\n\n    // relax edge e\n    private void relax(DirectedEdge e) {\n        int v = e.from(), w = e.to();\n        if (distTo[w] > distTo[v] + e.weight()) {\n            distTo[w] = distTo[v] + e.weight();\n            edgeTo[w] = e;\n        }\n    }\n\n    /**\n     * Returns the length of a shortest path from the source vertex {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return the length of a shortest path from the source vertex {@code s} to vertex {@code v};\n     *         {@code Double.POSITIVE_INFINITY} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public double distTo(int v) {\n        validateVertex(v);\n        return distTo[v];\n    }\n\n    /**\n     * Is there a path from the source vertex {@code s} to vertex {@code v}?\n     * @param  v the destination vertex\n     * @return {@code true} if there is a path from the source vertex\n     *         {@code s} to vertex {@code v}, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return distTo[v] < Double.POSITIVE_INFINITY;\n    }\n\n    /**\n     * Returns a shortest path from the source vertex {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return a shortest path from the source vertex {@code s} to vertex {@code v}\n     *         as an iterable of edges, and {@code null} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<DirectedEdge> path = new Stack<DirectedEdge>();\n        for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {\n            path.push(e);\n        }\n        return path;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = distTo.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code AcyclicSP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        int s = Integer.parseInt(args[1]);\n        EdgeWeightedDigraph digraph = new EdgeWeightedDigraph(in);\n\n        // find shortest path from s to each other vertex in DAG\n        AcyclicSP sp = new AcyclicSP(digraph, s);\n        for (int v = 0; v < digraph.V(); v++) {\n            if (sp.hasPathTo(v)) {\n                StdOut.printf(\"%d to %d (%.2f)  \", s, v, sp.distTo(v));\n                for (DirectedEdge e : sp.pathTo(v)) {\n                    StdOut.print(e + \"   \");\n                }\n                StdOut.println();\n            }\n            else {\n                StdOut.printf(\"%d to %d         no path\\n\", s, v);\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AdjMatrixEdgeWeightedDigraph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AdjMatrixEdgeWeightedDigraph.java\n *  Execution:    java AdjMatrixEdgeWeightedDigraph V E\n *  Dependencies: StdOut.java\n *\n *  An edge-weighted digraph, implemented using an adjacency matrix.\n *  Parallel edges are disallowed; self-loops are allowed.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code AdjMatrixEdgeWeightedDigraph} class represents an edge-weighted\n *  digraph of vertices named 0 through <em>V</em> - 1, where each\n *  directed edge is of type {@link DirectedEdge} and has a real-valued weight.\n *  It supports the following two primary operations: add a directed edge\n *  to the digraph and iterate over all of edges incident from a given vertex.\n *  It also provides\n *  methods for returning the number of vertices <em>V</em> and the number\n *  of edges <em>E</em>. Parallel edges are disallowed; self-loops are permitted.\n *  <p>\n *  This implementation uses an adjacency-matrix representation.\n *  All operations take constant time (in the worst case) except\n *  iterating over the edges incident from a given vertex, which takes\n *  time proportional to <em>V</em>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class AdjMatrixEdgeWeightedDigraph {\n    private static final String NEWLINE = System.getProperty(\"line.separator\");\n\n    private final int V;\n    private int E;\n    private DirectedEdge[][] adj;\n\n    /**\n     * Initializes an empty edge-weighted digraph with {@code V} vertices and 0 edges.\n     * @param V the number of vertices\n     * @throws IllegalArgumentException if {@code V < 0}\n     */\n    public AdjMatrixEdgeWeightedDigraph(int V) {\n        if (V < 0) throw new IllegalArgumentException(\"number of vertices must be non-negative\");\n        this.V = V;\n        this.E = 0;\n        this.adj = new DirectedEdge[V][V];\n    }\n\n    /**\n     * Initializes a random edge-weighted digraph with {@code V} vertices and <em>E</em> edges.\n     * @param V the number of vertices\n     * @param E the number of edges\n     * @throws IllegalArgumentException if {@code V < 0}\n     * @throws IllegalArgumentException if {@code E < 0}\n     */\n    public AdjMatrixEdgeWeightedDigraph(int V, int E) {\n        this(V);\n        if (E < 0) throw new IllegalArgumentException(\"number of edges must be non-negative\");\n        if (E > V*V) throw new IllegalArgumentException(\"too many edges\");\n\n        // can be inefficient\n        while (this.E != E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            double weight = 0.01 * StdRandom.uniformInt(0, 100);\n            addEdge(new DirectedEdge(v, w, weight));\n        }\n    }\n\n    /**\n     * Returns the number of vertices in the edge-weighted digraph.\n     * @return the number of vertices in the edge-weighted digraph\n     */\n    public int V() {\n        return V;\n    }\n\n    /**\n     * Returns the number of edges in the edge-weighted digraph.\n     * @return the number of edges in the edge-weighted digraph\n     */\n    public int E() {\n        return E;\n    }\n\n    /**\n     * Adds the directed edge {@code e} to the edge-weighted digraph (if there\n     * is not already an edge with the same endpoints).\n     * @param e the edge\n     */\n    public void addEdge(DirectedEdge e) {\n        int v = e.from();\n        int w = e.to();\n        validateVertex(v);\n        validateVertex(w);\n        if (adj[v][w] == null) {\n            E++;\n            adj[v][w] = e;\n        }\n    }\n\n    /**\n     * Returns the directed edges incident from vertex {@code v}.\n     * @param v the vertex\n     * @return the directed edges incident from vertex {@code v} as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> adj(int v) {\n        validateVertex(v);\n        return new AdjIterator(v);\n    }\n\n    // support iteration over graph vertices\n    private class AdjIterator implements Iterator<DirectedEdge>, Iterable<DirectedEdge> {\n        private int v;\n        private int w = 0;\n\n        public AdjIterator(int v) {\n            this.v = v;\n        }\n\n        public Iterator<DirectedEdge> iterator() {\n            return this;\n        }\n\n        public boolean hasNext() {\n            while (w < V) {\n                if (adj[v][w] != null) return true;\n                w++;\n            }\n            return false;\n        }\n\n        public DirectedEdge next() {\n            if (!hasNext()) {\n                throw new NoSuchElementException();\n            }\n            return adj[v][w++];\n        }\n\n        public void remove() {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    /**\n     * Returns a string representation of the edge-weighted digraph. This method takes\n     * time proportional to <em>V</em><sup>2</sup>.\n     * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,\n     *   followed by the <em>V</em> adjacency lists of edges\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(V + \" \" + E + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            s.append(v + \": \");\n            for (DirectedEdge e : adj(v)) {\n                s.append(e + \"  \");\n            }\n            s.append(NEWLINE);\n        }\n        return s.toString();\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n\n    /**\n     * Unit tests the {@code AdjMatrixEdgeWeightedDigraph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        AdjMatrixEdgeWeightedDigraph G = new AdjMatrixEdgeWeightedDigraph(V, E);\n        StdOut.println(G);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AllowFilter.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AllowFilter.java\n *  Execution:    java AllowFilter allowlist.txt < input.txt\n *  Dependencies: SET In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/tinyTale.txt\n *                https://algs4.cs.princeton.edu/35applications/allowlist.txt\n *\n *  Reads an allowlist of words from a file. Then readsa list of\n *  words from standard input and prints all those words that\n *  are in the first file.\n *\n *  % more tinyTale.txt\n *  it was the best of times it was the worst of times\n *  it was the age of wisdom it was the age of foolishness\n *  it was the epoch of belief it was the epoch of incredulity\n *  it was the season of light it was the season of darkness\n *  it was the spring of hope it was the winter of despair\n *\n *  % more list.txt\n *  was it the of\n *\n *  % java AllowFilter list.txt < tinyTale.txt\n *  it was the of it was the of\n *  it was the of it was the of\n *  it was the of it was the of\n *  it was the of it was the of\n *  it was the of it was the of\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code AllowFilter} class provides a client for reading in an <em>allowlist</em>\n *  of words from a file; then, reading in a sequence of words from standard input,\n *  printing out each word that appears in the file.\n *  It is useful as a test client for various symbol-table implementations.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class AllowFilter {\n\n    // Do not instantiate.\n    private AllowFilter() { }\n\n    public static void main(String[] args) {\n        SET<String> set = new SET<String>();\n\n        // read in strings and add to set\n        In in = new In(args[0]);\n        while (!in.isEmpty()) {\n            String word = in.readString();\n            set.add(word);\n        }\n\n        // read in string from standard input, printing out all exceptions\n        while (!StdIn.isEmpty()) {\n            String word = StdIn.readString();\n            if (set.contains(word))\n                StdOut.println(word);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Allowlist.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Allowlist.java\n *  Execution:    java Allowlist allowlist.txt < data.txt\n *  Dependencies: StaticSetOfInts.java In.java StdOut.java\n *\n *  Data files:   https://algs4.cs.princeton.edu/11model/tinyAllowlist.txt\n *                https://algs4.cs.princeton.edu/11model/tinyText.txt\n *                https://algs4.cs.princeton.edu/11model/largeAllowlist.txt\n *                https://algs4.cs.princeton.edu/11model/largeText.txt\n *\n *  Allowlist filter.\n *\n *\n *  % java Allowlist tinyAllowlist.txt < tinyText.txt\n *  50\n *  99\n *  13\n *\n *  % java Allowlist largeAllowlist.txt < largeText.txt | more\n *  499569\n *  984875\n *  295754\n *  207807\n *  140925\n *  161828\n *  [367,966 total values]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Allowlist} class provides a client for reading in\n *  a set of integers from a file; reading in a sequence of integers\n *  from standard input; and printing to standard output those\n *  integers not in the allowlist.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Allowlist {\n\n    // Do not instantiate.\n    private Allowlist() { }\n\n    /**\n     * Reads in a sequence of integers from the allowlist file, specified as\n     * a command-line argument. Reads in integers from standard input and\n     * prints to standard output those integers that are not in the file.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        int[] white = in.readAllInts();\n        StaticSETofInts set = new StaticSETofInts(white);\n\n        // Read key, print if not in allowlist.\n        while (!StdIn.isEmpty()) {\n            int key = StdIn.readInt();\n            if (!set.contains(key))\n                StdOut.println(key);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Alphabet.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Alphabet.java\n *  Execution:    java Alphabet\n *  Dependencies: StdOut.java\n *  \n *  A data type for alphabets, for use with string-processing code\n *  that must convert between an alphabet of size R and the integers\n *  0 through R-1.\n *\n *  Warning: supports only the basic multilingual plane (BMP), i.e,\n *           Unicode characters between U+0000 and U+FFFF.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\npublic class Alphabet {\n\n    /**\n     *  The binary alphabet { 0, 1 }.\n     */\n    public static final Alphabet BINARY = new Alphabet(\"01\");\n\n    /**\n     *  The octal alphabet { 0, 1, 2, 3, 4, 5, 6, 7 }.\n     */\n    public static final Alphabet OCTAL = new Alphabet(\"01234567\");\n\n    /**\n     *  The decimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.\n     */\n    public static final Alphabet DECIMAL = new Alphabet(\"0123456789\");\n\n    /**\n     *  The hexadecimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F }.\n     */\n    public static final Alphabet HEXADECIMAL = new Alphabet(\"0123456789ABCDEF\");\n\n    /**\n     *  The DNA alphabet { A, C, T, G }.\n     */\n    public static final Alphabet DNA = new Alphabet(\"ACGT\");\n\n    /**\n     *  The lowercase alphabet { a, b, c, ..., z }.\n     */\n    public static final Alphabet LOWERCASE = new Alphabet(\"abcdefghijklmnopqrstuvwxyz\");\n\n    /**\n     *  The uppercase alphabet { A, B, C, ..., Z }.\n     */\n\n    public static final Alphabet UPPERCASE = new Alphabet(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n\n    /**\n     *  The protein alphabet { A, C, D, E, F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, Y }.\n     */\n    public static final Alphabet PROTEIN = new Alphabet(\"ACDEFGHIKLMNPQRSTVWY\");\n\n    /**\n     *  The base-64 alphabet (64 characters).\n     */\n    public static final Alphabet BASE64 = new Alphabet(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\");\n\n    /**\n     *  The ASCII alphabet (0-127).\n     */\n    public static final Alphabet ASCII = new Alphabet(128);\n\n    /**\n     *  The extended ASCII alphabet (0-255).\n     */\n    public static final Alphabet EXTENDED_ASCII = new Alphabet(256);\n\n    /**\n     *  The Unicode 16 alphabet (0-65,535).\n     */\n    public static final Alphabet UNICODE16      = new Alphabet(65536);\n\n\n    private char[] alphabet;     // the characters in the alphabet\n    private int[] inverse;       // indices\n    private final int R;         // the radix of the alphabet\n\n    /**\n     * Initializes a new alphabet from the given set of characters.\n     *\n     * @param alpha the set of characters\n     */\n    public Alphabet(String alpha) {\n\n        // check that alphabet contains no duplicate chars\n        boolean[] unicode = new boolean[Character.MAX_VALUE];\n        for (int i = 0; i < alpha.length(); i++) {\n            char c = alpha.charAt(i);\n            if (unicode[c])\n                throw new IllegalArgumentException(\"Illegal alphabet: repeated character = '\" + c + \"'\");\n            unicode[c] = true;\n        }\n\n        alphabet = alpha.toCharArray();\n        R = alpha.length();\n        inverse = new int[Character.MAX_VALUE];\n        for (int i = 0; i < inverse.length; i++)\n            inverse[i] = -1;\n\n        // can't use char since R can be as big as 65,536\n        for (int c = 0; c < R; c++)\n            inverse[alphabet[c]] = c;\n    }\n\n    /**\n     * Initializes a new alphabet using characters 0 through R-1.\n     *\n     * @param radix the number of characters in the alphabet (the radix R)\n     */\n    private Alphabet(int radix) {\n        this.R = radix;\n        alphabet = new char[R];\n        inverse = new int[R];\n\n        // can't use char since R can be as big as 65,536\n        for (int i = 0; i < R; i++)\n            alphabet[i] = (char) i;\n        for (int i = 0; i < R; i++)\n            inverse[i] = i;\n    }\n\n    /**\n     * Initializes a new alphabet using characters 0 through 255.\n     */\n    public Alphabet() {\n        this(256);\n    }\n\n    /**\n     * Returns true if the argument is a character in this alphabet.\n     *\n     * @param  c the character\n     * @return {@code true} if {@code c} is a character in this alphabet;\n     *         {@code false} otherwise\n     */\n    public boolean contains(char c) {\n        return inverse[c] != -1;\n    }\n\n    /**\n     * Returns the number of characters in this alphabet (the radix).\n     * \n     * @return the number of characters in this alphabet\n     * @deprecated Replaced by {@link #radix()}.\n     */\n    @Deprecated\n    public int R() {\n        return R;\n    }\n\n    /**\n     * Returns the number of characters in this alphabet (the radix).\n     * \n     * @return the number of characters in this alphabet\n     */\n    public int radix() {\n        return R;\n    }\n\n    /**\n     * Returns the binary logarithm of the number of characters in this alphabet.\n     * \n     * @return the binary logarithm (rounded up) of the number of characters in this alphabet\n     */\n    public int lgR() {\n        int lgR = 0;\n        for (int t = R-1; t >= 1; t /= 2)\n            lgR++;\n        return lgR;\n    }\n\n    /**\n     * Returns the index corresponding to the argument character.\n     * \n     * @param  c the character\n     * @return the index corresponding to the character {@code c}\n     * @throws IllegalArgumentException unless {@code c} is a character in this alphabet\n     */\n    public int toIndex(char c) {\n        if (c >= inverse.length || inverse[c] == -1) {\n            throw new IllegalArgumentException(\"Character \" + c + \" not in alphabet\");\n        }\n        return inverse[c];\n    }\n\n    /**\n     * Returns the indices corresponding to the argument characters.\n     * \n     * @param  s the characters\n     * @return the indices corresponding to the characters {@code s}\n     * @throws IllegalArgumentException unless every character in {@code s}\n     *         is a character in this alphabet\n     */\n    public int[] toIndices(String s) {\n        char[] source = s.toCharArray();\n        int[] target  = new int[s.length()];\n        for (int i = 0; i < source.length; i++)\n            target[i] = toIndex(source[i]);\n        return target;\n    }\n\n    /**\n     * Returns the character corresponding to the argument index.\n     * \n     * @param  index the index\n     * @return the character corresponding to the index {@code index}\n     * @throws IllegalArgumentException unless {@code 0 <= index < R}\n     */\n    public char toChar(int index) {\n        if (index < 0 || index >= R) {\n            throw new IllegalArgumentException(\"index must be between 0 and \" + R + \": \" + index);\n        }\n        return alphabet[index];\n    }\n\n    /**\n     * Returns the characters corresponding to the argument indices.\n     * \n     * @param  indices the indices\n     * @return the characters corresponding to the indices {@code indices}\n     * @throws IllegalArgumentException unless {@code 0 < indices[i] < R}\n     *         for every {@code i}\n     */\n    public String toChars(int[] indices) {\n        StringBuilder s = new StringBuilder(indices.length);\n        for (int i = 0; i < indices.length; i++)\n            s.append(toChar(indices[i]));\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code Alphabet} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int[]  encoded1 = Alphabet.BASE64.toIndices(\"NowIsTheTimeForAllGoodMen\");\n        String decoded1 = Alphabet.BASE64.toChars(encoded1);\n        StdOut.println(decoded1);\n \n        int[]  encoded2 = Alphabet.DNA.toIndices(\"AACGAACGGTTTACCCCG\");\n        String decoded2 = Alphabet.DNA.toChars(encoded2);\n        StdOut.println(decoded2);\n\n        int[]  encoded3 = Alphabet.DECIMAL.toIndices(\"01234567890123456789\");\n        String decoded3 = Alphabet.DECIMAL.toChars(encoded3);\n        StdOut.println(decoded3);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AmericanFlag.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AmericanFlag.java\n *  Execution:    java AmericanFlag < input.txt\n *                java AmericanFlag int < input-non-negative-ints.txt\n *  Dependencies: StdIn.java StdOut.java Stack.java\n *  Data files:   https://algs4.cs.princeton.edu/51radix/words3.txt\n *                https://algs4.cs.princeton.edu/51radix/shells.txt\n *\n *  Sort an array of strings or integers in-place using American flag sort.\n *\n *  % java AmericanFlag < shells.txt\n *  are\n *  by\n *  sea\n *  seashells\n *  seashells\n *  sells\n *  sells\n *  she\n *  she\n *  shells\n *  shore\n *  surely\n *  the\n *  the\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code AmericanFlag} class provides static methods for sorting an\n *  array of extended ASCII strings or integers in-place using\n *  American flag sort. This is a non-recursive implementation.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/51radix\">Section 5.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne\n *  and <a href = \"http://static.usenix.org/publications/compsystems/1993/win_mcilroy.pdf\">\n *  Engineering Radix Sort</a> by McIlroy and Bostic.\n *  For a version that uses only one auxiliary array, see {@link AmericanFlagX}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *  @author Ivan Pesin\n */\n\npublic class AmericanFlag {\n    private static final int BITS_PER_BYTE =   8;\n    private static final int BITS_PER_INT  =  32;   // each Java int is 32 bits\n    private static final int R             = 256;   // extend ASCII alphabet size\n    private static final int CUTOFF        =  15;   // cutoff to insertion sort\n\n    // do not instantiate\n    private AmericanFlag() { }\n\n    // return dth character of s, -1 if d = length of string\n    private static int charAt(String s, int d) {\n        assert d >= 0 && d <= s.length();\n        if (d == s.length()) return -1;\n        return s.charAt(d);\n    }\n\n    /**\n     * Rearranges the array of extended ASCII strings in ascending order.\n     * This is an unstable sorting algorithm.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(String[] a) {\n        sort(a, 0, a.length - 1);\n    }\n\n    // sort from a[lo] to a[hi], starting at the dth character\n    public static void sort(String[] a, int lo, int hi) {\n        // one-time allocation of data structures\n        Stack<Integer> st = new Stack<Integer>();\n        int[] first = new int[R+2];\n        int[] next  = new int[R+2];\n        int d = 0; // character index to sort by\n\n        st.push(lo);\n        st.push(hi);\n        st.push(d);\n\n        while (!st.isEmpty()) {\n            d = st.pop();\n            hi = st.pop();\n            lo = st.pop();\n\n            if (hi <= lo + CUTOFF) {\n                insertion(a, lo, hi, d);\n                continue;\n            }\n\n            // compute frequency counts\n            for (int i = lo; i <= hi; i++) {\n                int c = charAt(a[i], d) + 1; // account for -1 representing end-of-string\n                first[c+1]++;\n            }\n\n            // first[c] = location of first string whose dth character = c\n            first[0] = lo;\n            for (int c = 0; c <= R; c++) {\n                first[c+1] += first[c];\n\n                if (c > 0 && first[c+1]-1 > first[c]) {\n                    // add subproblem for character c (excludes sentinel c == 0)\n                    st.push(first[c]);\n                    st.push(first[c+1] - 1);\n                    st.push(d+1);\n                }\n            }\n\n            // next[c] = location to place next string whose dth character = c\n            for (int c = 0; c < R+2; c++)\n                next[c] = first[c];\n\n            // permute data in place\n            for (int k = lo; k <= hi; k++) {\n                int c = charAt(a[k], d) + 1;\n                while (first[c] > k) {\n                    exch(a, k, next[c]++);\n                    c = charAt(a[k], d) + 1;\n                }\n                next[c]++;\n            }\n\n            // clear first[] and next[] arrays\n            for (int c = 0; c < R+2; c++) {\n                first[c] = 0;\n                next[c] = 0;\n            }\n        }\n    }\n\n    // insertion sort a[lo..hi], starting at dth character\n    private static void insertion(String[] a, int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], d); j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(String[] a, int i, int j) {\n        String temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n    // is v less than w, starting at character d\n    private static boolean less(String v, String w, int d) {\n        // assert v.substring(0, d).equals(w.substring(0, d));\n        for (int i = d; i <  Math.min(v.length(), w.length()); i++) {\n            if (v.charAt(i) < w.charAt(i)) return true;\n            if (v.charAt(i) > w.charAt(i)) return false;\n        }\n        return v.length() < w.length();\n    }\n\n   /**\n     * Rearranges the array of 32-bit integers in ascending order.\n     * Currently, assumes that the integers are nonnegative.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(int[] a) {\n        sort(a, 0, a.length-1);\n    }\n\n    // MSD sort from a[lo] to a[hi]\n    private static void sort(int[] a, int lo, int hi) {\n        // one-time allocation of data structures\n        Stack<Integer> st = new Stack<Integer>();\n        int[] first = new int[R+1];\n        int[] next  = new int[R+1];\n        int mask = R - 1;   // 0xFF;\n        int d = 0;          // byte to sort by\n\n        st.push(lo);\n        st.push(hi);\n        st.push(d);\n\n        while (!st.isEmpty()) {\n            d = st.pop();\n            hi = st.pop();\n            lo = st.pop();\n\n            if (hi <= lo + CUTOFF) {\n                insertion(a, lo, hi, d);\n                continue;\n            }\n\n            // compute frequency counts (need R = 256)\n            int shift = BITS_PER_INT - BITS_PER_BYTE*d - BITS_PER_BYTE;\n            for (int i = lo; i <= hi; i++) {\n                int c = (a[i] >> shift) & mask;\n                first[c+1]++;\n            }\n\n            // first[c] = location of first int whose dth byte = c\n            first[0] = lo;\n            for (int c = 0; c < R; c++) {\n                first[c+1] += first[c];\n\n                if (d < 3 && first[c+1]-1 > first[c]) {\n                    // add subproblem for byte c\n                    st.push(first[c]);\n                    st.push(first[c+1] - 1);\n                    st.push(d+1);\n                }\n            }\n\n            // next[c] = location to place next string whose dth byte = c\n            for (int c = 0; c < R+1; c++)\n                next[c] = first[c];\n\n            // permute data in place\n            for (int k = lo; k <= hi; k++) {\n                int c = (a[k] >> shift) & mask;\n                while (first[c] > k) {\n                    exch(a, k, next[c]++);\n                    c = (a[k] >> shift) & mask;\n                }\n                next[c]++;\n            }\n\n            // clear first[] and next[] arrays\n            for (int c = 0; c < R+1; c++) {\n                first[c] = 0;\n                next[c] = 0;\n            }\n        }\n    }\n\n    // insertion sort a[lo..hi], starting at dth byte\n    private static void insertion(int[] a, int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], d); j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(int[] a, int i, int j) {\n        int temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n    // is v less than w, starting at byte d\n    private static boolean less(int v, int w, int d) {\n        int mask = R - 1;   // 0xFF;\n        for (int i = d; i < 4; i++) {\n            int shift = BITS_PER_INT - BITS_PER_BYTE*i - BITS_PER_BYTE;\n            int a = (v >> shift) & mask;\n            int b = (w >> shift) & mask;\n            if (a < b) return true;\n            if (a > b) return false;\n        }\n        return false;\n    }\n\n    /**\n     * Reads in a sequence of extended ASCII strings or non-negative ints from standard input;\n     * American flag sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments: \"int\" to read input as non-negative integers\n     */\n    public static void main(String[] args) {\n        if (args.length > 0 && args[0].equals(\"int\")) {\n            int[] a = StdIn.readAllInts();\n            sort(a);\n\n            // print results\n            for (int i = 0; i < a.length; i++)\n                StdOut.println(a[i]);\n        }\n\n        else {\n            String[] a = StdIn.readAllStrings();\n            sort(a);\n            // print results\n            for (int i = 0; i < a.length; i++)\n                StdOut.println(a[i]);\n        }\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AmericanFlagX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AmericanFlagX.java\n *  Execution:    java AmericanFlagX < input.txt\n *  Dependencies: StdIn.java StdOut.java Stack.java\n *  Data files:   https://algs4.cs.princeton.edu/51radix/words3.txt\n *                https://algs4.cs.princeton.edu/51radix/shells.txt\n *\n *  Sort an array of strings or integers in-place using American Flag sort.\n *\n *  % java AmericanFlagX < shells.txt\n *  are\n *  by\n *  sea\n *  seashells\n *  seashells\n *  sells\n *  sells\n *  she\n *  she\n *  shells\n *  shore\n *  surely\n *  the\n *  the\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code AmericanFlagX} class provides static methods for sorting an\n *  array of extended ASCII strings or integers in-place using\n *  American Flag sort. This implementation is non-recursive and uses only\n *  one auxiliary array.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/51radix\">Section 5.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne\n *  and <a href = \"http://static.usenix.org/publications/compsystems/1993/win_mcilroy.pdf\">\n *  Engineering Radix Sort</a> by McIlroy and Bostic.\n *  For a version that uses two auxiliary arrays, see {@link AmericanFlag}.\n *\n *  @author Ivan Pesin\n */\n\npublic class AmericanFlagX {\n    private static final int R      = 256;   // extend ASCII alphabet size\n    private static final int CUTOFF =  15;   // cutoff to insertion sort\n\n    // do not instantiate\n    private AmericanFlagX() { }\n\n    // return dth character of s, -1 if d = length of string\n    private static int charAt(String s, int d) {\n        assert d >= 0 && d <= s.length();\n        if (d == s.length()) return -1;\n        return s.charAt(d);\n    }\n\n    /**\n     * Rearranges the array of extended ASCII strings in ascending order.\n     * This is an unstable in-place sorting algorithm.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(String[] a) {\n        sort(a, 0, a.length - 1);\n    }\n\n    // sort from a[lo] to a[hi], starting at the dth character\n    public static void sort(String[] a, int lo, int hi) {\n        // one-time allocation of data structures\n        Stack<Integer> st = new Stack<Integer>();\n        int[] count = new int[R+1];\n        int d = 0; // character index to sort by\n\n        st.push(lo);\n        st.push(hi);\n        st.push(d);\n\n        while (!st.isEmpty()) {\n            d = st.pop();\n            hi = st.pop();\n            lo = st.pop();\n\n            if (hi <= lo + CUTOFF) {\n                insertion(a, lo, hi, d);\n                continue;\n            }\n\n            // compute frequency counts\n            for (int i = lo; i <= hi; i++) {\n                int c = charAt(a[i], d) + 1; // account for -1 representing end-of-string\n                count[c]++;\n            }\n\n            // accumulate counts relative to a[0], so that\n            // count[c] is the number of keys <= c\n            count[0] += lo;\n            for (int c = 0; c < R; c++) {\n                count[c+1] += count[c];\n\n                if (c > 0 && count[c+1]-1 > count[c]) {\n                    // add subproblem for character c (excludes sentinel c == 0)\n                    st.push(count[c]);\n                    st.push(count[c+1]-1);\n                    st.push(d+1);\n                }\n            }\n\n            // permute data in place\n            // for details and proof see Knuth Theorem 5.1.2B and ch 5.2 exercise 13.\n            for (int r = hi; r >= lo; r--) {\n\n                // locate element that must be shifted right of r\n                int c = charAt(a[r], d) + 1;\n                while (r >= lo && count[c]-1 <= r) {\n                    if (count[c]-1 == r) count[c]--;\n                    r--;\n                    if (r >= lo) c = charAt(a[r], d) + 1;\n                }\n\n                // if r < lo the subarray is sorted.\n                if (r < lo) break;\n\n                // permute a[r] until correct element is in place\n                while (--count[c] != r) {\n                    exch(a, r, count[c]);\n                    c = charAt(a[r], d) + 1;\n                }\n            }\n\n            // clear count[] array\n            for (int c = 0; c < R+1; c++)\n                count[c] = 0;\n        }\n    }\n\n    // insertion sort a[lo..hi], starting at dth character\n    private static void insertion(String[] a, int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], d); j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(String[] a, int i, int j) {\n        String temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n    // is v less than w, starting at character d\n    private static boolean less(String v, String w, int d) {\n        // assert v.substring(0, d).equals(w.substring(0, d));\n        for (int i = d; i <  Math.min(v.length(), w.length()); i++) {\n            if (v.charAt(i) < w.charAt(i)) return true;\n            if (v.charAt(i) > w.charAt(i)) return false;\n        }\n        return v.length() < w.length();\n    }\n\n    /**\n     * Reads in a sequence of extended ASCII strings or non-negative ints from standard input;\n     * American flag sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        sort(a);\n        // print results\n        for (int i = 0; i < a.length; i++)\n            StdOut.println(a[i]);\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Arbitrage.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Arbitrage.java\n *  Execution:    java Arbitrage < input.txt\n *  Dependencies: EdgeWeightedDigraph.java DirectedEdge.java\n *                BellmanFordSP.java\n *  Data file:    https://algs4.cs.princeton.edu/44sp/rates.txt\n *\n *  Arbitrage detection.\n *\n *  % more rates.txt\n *  5\n *  USD 1      0.741  0.657  1.061  1.005\n *  EUR 1.349  1      0.888  1.433  1.366\n *  GBP 1.521  1.126  1      1.614  1.538\n *  CHF 0.942  0.698  0.619  1      0.953\n *  CAD 0.995  0.732  0.650  1.049  1\n *\n *  % java Arbitrage < rates.txt\n *  1000.00000 USD =  741.00000 EUR\n *   741.00000 EUR = 1012.20600 CAD\n *  1012.20600 CAD = 1007.14497 USD\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Arbitrage} class provides a client that finds an arbitrage\n *  opportunity in a currency exchange table by constructing a\n *  complete-digraph representation of the exchange table and then finding\n *  a negative cycle in the digraph.\n *  <p>\n *  This implementation uses the Bellman-Ford algorithm to find a\n *  negative cycle in the complete digraph.\n *  The running time is proportional to <em>V</em><sup>3</sup> in the\n *  worst case, where <em>V</em> is the number of currencies.\n *  <p>\n *  This code is guaranteed to find an arbitrage opportunity in a\n *  currency exchange table (or report that no such arbitrage\n *  opportunity exists) under the assumption that all arithmetic\n *  performed is without floating-point rounding error or arithmetic\n *  overflow. Since the code computes the logarithms of the edge weights,\n *  floating-point rounding error will be present, and it may fail on\n *  some pathological inputs.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Arbitrage {\n\n    // this class cannot be instantiated\n    private Arbitrage() { }\n\n    /**\n     *  Reads the currency exchange table from standard input and\n     *  prints an arbitrage opportunity to standard output (if one exists).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // V currencies\n        int V = StdIn.readInt();\n        String[] name = new String[V];\n\n        // create complete network\n        EdgeWeightedDigraph G = new EdgeWeightedDigraph(V);\n        for (int v = 0; v < V; v++) {\n            name[v] = StdIn.readString();\n            for (int w = 0; w < V; w++) {\n                double rate = StdIn.readDouble();\n                DirectedEdge e = new DirectedEdge(v, w, -Math.log(rate));\n                G.addEdge(e);\n            }\n        }\n\n        // find negative cycle\n        BellmanFordSP spt = new BellmanFordSP(G, 0);\n        if (spt.hasNegativeCycle()) {\n            double stake = 1000.0;\n            for (DirectedEdge e : spt.negativeCycle()) {\n                StdOut.printf(\"%10.5f %s \", stake, name[e.from()]);\n                stake *= Math.exp(-e.weight());\n                StdOut.printf(\"= %10.5f %s\\n\", stake, name[e.to()]);\n            }\n        }\n        else {\n            StdOut.println(\"No arbitrage opportunity\");\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/AssignmentProblem.java",
    "content": "/******************************************************************************\n *  Compilation:  javac AssignmentProblem.java\n *  Execution:    java AssignmentProblem n\n *  Dependencies: DijkstraSP.java DirectedEdge.java\n *\n *  Solve an n-by-n assignment problem in n^3 log n time using the\n *  successive shortest path algorithm.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code AssignmentProblem} class represents a data type for computing\n *  an optimal solution to an <em>n</em>-by-<em>n</em> <em>assignment problem</em>.\n *  The assignment problem is to find a minimum weight matching in an\n *  edge-weighted complete bipartite graph.\n *  <p>\n *  The data type supplies methods for determining the optimal solution\n *  and the corresponding dual solution.\n *  <p>\n *  This implementation uses the <em>successive shortest paths algorithm</em>.\n *  The order of growth of the running time in the worst case is\n *  O(<em>n</em>^3 log <em>n</em>) to solve an <em>n</em>-by-<em>n</em>\n *  instance.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/65reductions\">Section 6.5</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class AssignmentProblem {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-14;\n    private static final int UNMATCHED = -1;\n\n    private int n;              // number of rows and columns\n    private double[][] weight;  // the n-by-n cost matrix\n    private double minWeight;   // minimum value of any weight\n    private double[] px;        // px[i] = dual variable for row i\n    private double[] py;        // py[j] = dual variable for col j\n    private int[] xy;           // xy[i] = j means i-j is a match\n    private int[] yx;           // yx[j] = i means i-j is a match\n\n    /**\n     * Determines an optimal solution to the assignment problem.\n     *\n     * @param  weight the <em>n</em>-by-<em>n</em> matrix of weights\n     * @throws IllegalArgumentException unless all weights are nonnegative\n     * @throws IllegalArgumentException if {@code weight} is {@code null}\n     */\n    public AssignmentProblem(double[][] weight) {\n        if (weight == null) throw new IllegalArgumentException(\"constructor argument is null\");\n\n        n = weight.length;\n        this.weight = new double[n][n];\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (Double.isNaN(weight[i][j]))\n                    throw new IllegalArgumentException(\"weight \" + i + \"-\" + j  + \" is NaN\");\n                if (weight[i][j] < minWeight) minWeight = weight[i][j];\n                this.weight[i][j] = weight[i][j];\n            }\n        }\n\n        // dual variables\n        px = new double[n];\n        py = new double[n];\n\n        // initial matching is empty\n        xy = new int[n];\n        yx = new int[n];\n        for (int i = 0; i < n; i++)\n             xy[i] = UNMATCHED;\n        for (int j = 0; j < n; j++)\n             yx[j] = UNMATCHED;\n\n        // add n edges to matching\n        for (int k = 0; k < n; k++) {\n            assert isDualFeasible();\n            assert isComplementarySlack();\n            augment();\n        }\n        assert certifySolution();\n    }\n\n    // find shortest augmenting path and update\n    private void augment() {\n\n        // build residual graph\n        EdgeWeightedDigraph G = new EdgeWeightedDigraph(2*n+2);\n        int s = 2*n, t = 2*n+1;\n        for (int i = 0; i < n; i++) {\n            if (xy[i] == UNMATCHED)\n                G.addEdge(new DirectedEdge(s, i, 0.0));\n        }\n        for (int j = 0; j < n; j++) {\n            if (yx[j] == UNMATCHED)\n                G.addEdge(new DirectedEdge(n+j, t, py[j]));\n        }\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (xy[i] == j) G.addEdge(new DirectedEdge(n+j, i, 0.0));\n                else            G.addEdge(new DirectedEdge(i, n+j, reducedCost(i, j)));\n            }\n        }\n\n        // compute shortest path from s to every other vertex\n        DijkstraSP spt = new DijkstraSP(G, s);\n\n        // augment along alternating path\n        for (DirectedEdge e : spt.pathTo(t)) {\n            int i = e.from(), j = e.to() - n;\n            if (i < n) {\n                xy[i] = j;\n                yx[j] = i;\n            }\n        }\n\n        // update dual variables\n        for (int i = 0; i < n; i++)\n            px[i] += spt.distTo(i);\n        for (int j = 0; j < n; j++)\n            py[j] += spt.distTo(n+j);\n    }\n\n    // reduced cost of i-j\n    // (subtracting off minWeight re-weights all weights to be non-negative)\n    private double reducedCost(int i, int j) {\n        double reducedCost = (weight[i][j] - minWeight) + px[i] - py[j];\n\n        // to avoid issues with floating-point precision\n        double magnitude = Math.abs(weight[i][j]) + Math.abs(px[i]) + Math.abs(py[j]);\n        if (Math.abs(reducedCost) <= FLOATING_POINT_EPSILON * magnitude) return 0.0;\n\n        assert reducedCost >= 0.0;\n        return reducedCost;\n    }\n\n    /**\n     * Returns the dual optimal value for the specified row.\n     *\n     * @param  i the row index\n     * @return the dual optimal value for row {@code i}\n     * @throws IllegalArgumentException unless {@code 0 <= i < n}\n     *\n     */\n    // dual variable for row i\n    public double dualRow(int i) {\n        validate(i);\n        return px[i];\n    }\n\n    /**\n     * Returns the dual optimal value for the specified column.\n     *\n     * @param  j the column index\n     * @return the dual optimal value for column {@code j}\n     * @throws IllegalArgumentException unless {@code 0 <= j < n}\n     *\n     */\n    public double dualCol(int j) {\n        validate(j);\n        return py[j];\n    }\n\n    /**\n     * Returns the column associated with the specified row in the optimal solution.\n     *\n     * @param  i the row index\n     * @return the column matched to row {@code i} in the optimal solution\n     * @throws IllegalArgumentException unless {@code 0 <= i < n}\n     *\n     */\n    public int sol(int i) {\n        validate(i);\n        return xy[i];\n    }\n\n    /**\n     * Returns the total weight of the optimal solution\n     *\n     * @return the total weight of the optimal solution\n     *\n     */\n    public double weight() {\n        double total = 0.0;\n        for (int i = 0; i < n; i++) {\n            if (xy[i] != UNMATCHED)\n                total += weight[i][xy[i]];\n        }\n        return total;\n    }\n\n    private void validate(int i) {\n        if (i < 0 || i >= n) throw new IllegalArgumentException(\"index is not between 0 and \" + (n-1) + \": \" + i);\n    }\n\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // check that dual variables are feasible\n    private boolean isDualFeasible() {\n        // check that all edges have >= 0 reduced cost\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (reducedCost(i, j) < 0) {\n                    StdOut.println(\"Dual variables are not feasible\");\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    // check that primal and dual variables are complementary slack\n    private boolean isComplementarySlack() {\n\n        // check that all matched edges have 0-reduced cost\n        for (int i = 0; i < n; i++) {\n            if ((xy[i] != UNMATCHED) && (reducedCost(i, xy[i]) != 0)) {\n                StdOut.println(\"Primal and dual variables are not complementary slack\");\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // check that primal variables are a perfect matching\n    private boolean isPerfectMatching() {\n\n        // check that xy[] is a perfect matching\n        boolean[] perm = new boolean[n];\n        for (int i = 0; i < n; i++) {\n            if (perm[xy[i]]) {\n                StdOut.println(\"Not a perfect matching\");\n                return false;\n            }\n            perm[xy[i]] = true;\n        }\n\n        // check that xy[] and yx[] are inverses\n        for (int j = 0; j < n; j++) {\n            if (xy[yx[j]] != j) {\n                StdOut.println(\"xy[] and yx[] are not inverses\");\n                return false;\n            }\n        }\n        for (int i = 0; i < n; i++) {\n            if (yx[xy[i]] != i) {\n                StdOut.println(\"xy[] and yx[] are not inverses\");\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    // check optimality conditions\n    private boolean certifySolution() {\n        return isPerfectMatching() && isDualFeasible() && isComplementarySlack();\n    }\n\n    /**\n     * Unit tests the {@code AssignmentProblem} data type.\n     * Takes a command-line argument n; creates a random n-by-n matrix;\n     * solves the n-by-n assignment problem; and prints the optimal\n     * solution.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // create random n-by-n matrix\n        int n = Integer.parseInt(args[0]);\n        double[][] weight = new double[n][n];\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                weight[i][j] = StdRandom.uniformInt(900) + 100;  // 3 digits\n            }\n        }\n\n        // solve assignment problem\n        AssignmentProblem assignment = new AssignmentProblem(weight);\n        StdOut.printf(\"weight = %.0f\\n\", assignment.weight());\n        StdOut.println();\n\n        // print n-by-n matrix and optimal solution\n        if (n >= 20) return;\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (j == assignment.sol(i))\n                    StdOut.printf(\"*%.0f \", weight[i][j]);\n                else\n                    StdOut.printf(\" %.0f \", weight[i][j]);\n            }\n            StdOut.println();\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Average.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Average.java\n *  Execution:    java Average < data.txt\n *  Dependencies: StdIn.java StdOut.java\n *\n *  Reads in a sequence of real numbers, and computes their average.\n *\n *  % java Average\n *  10.0 5.0 6.0\n *  3.0 7.0 32.0\n *  [Ctrl-d]\n *  Average is 10.5\n *\n *  Note [Ctrl-d] signifies the end of file on Unix.\n *  On windows use [Ctrl-z].\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Average} class provides a client for reading in a sequence\n *  of real numbers and printing out their average.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/11model\">Section 1.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Average {\n\n    // this class should not be instantiated\n    private Average() { }\n\n    /**\n     * Reads in a sequence of real numbers from standard input and prints\n     * out their average to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int count = 0;       // number input values\n        double sum = 0.0;    // sum of input values\n\n        // read data and compute statistics\n        while (!StdIn.isEmpty()) {\n            double value = StdIn.readDouble();\n            sum += value;\n            count++;\n        }\n\n        // compute the average\n        double average = sum / count;\n\n        // print results\n        StdOut.println(\"Average is \" + average);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BST.java\n *  Execution:    java BST\n *  Dependencies: StdIn.java StdOut.java Queue.java\n *  Data files:   https://algs4.cs.princeton.edu/32bst/tinyST.txt\n *\n *  A symbol table implemented with a binary search tree.\n *\n *  % more tinyST.txt\n *  S E A R C H E X A M P L E\n *\n *  % java BST < tinyST.txt\n *  A 8\n *  C 4\n *  E 12\n *  H 5\n *  L 11\n *  M 9\n *  P 10\n *  R 3\n *  S 0\n *  X 7\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code BST} class represents an ordered symbol table of generic\n *  key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides ordered methods for finding the <em>minimum</em>,\n *  <em>maximum</em>, <em>floor</em>, <em>select</em>, <em>ceiling</em>.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  It requires that\n *  the key type implements the {@code Comparable} interface and calls the\n *  {@code compareTo()} and method to compare two keys. It does not call either\n *  {@code equals()} or {@code hashCode()}.\n *  <p>\n *  This implementation uses an (unbalanced) <em>binary search tree</em>.\n *  The <em>put</em>, <em>contains</em>, <em>remove</em>, <em>minimum</em>,\n *  <em>maximum</em>, <em>ceiling</em>, <em>floor</em>, <em>select</em>, and\n *  <em>rank</em>  operations each take &Theta;(<em>n</em>) time in the worst\n *  case, where <em>n</em> is the number of key-value pairs.\n *  The <em>size</em> and <em>is-empty</em> operations take &Theta;(1) time.\n *  The keys method takes &Theta;(<em>n</em>) time in the worst case.\n *  Construction takes &Theta;(1) time.\n *  <p>\n *  For alternative implementations of the symbol table API, see {@link ST},\n *  {@link BinarySearchST}, {@link SequentialSearchST}, {@link RedBlackBST},\n *  {@link SeparateChainingHashST}, and {@link LinearProbingHashST},\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/32bst\">Section 3.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BST<Key extends Comparable<Key>, Value> {\n    private Node root;             // root of BST\n\n    private class Node {\n        private Key key;           // sorted by key\n        private Value val;         // associated data\n        private Node left, right;  // left and right subtrees\n        private int size;          // number of nodes in subtree\n\n        public Node(Key key, Value val, int size) {\n            this.key = key;\n            this.val = val;\n            this.size = size;\n        }\n    }\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public BST() {\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     * @return {@code true} if this symbol table is empty; {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return size(root);\n    }\n\n    // return number of key-value pairs in BST rooted at x\n    private int size(Node node) {\n        if (node == null) return 0;\n        else return node.size;\n    }\n\n    /**\n     * Does this symbol table contain the given key?\n     *\n     * @param  key the key\n     * @return {@code true} if this symbol table contains {@code key} and\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        return get(key) != null;\n    }\n\n    /**\n     * Returns the value associated with the given key.\n     *\n     * @param  key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *         and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        return get(root, key);\n    }\n\n    private Value get(Node node, Key key) {\n        if (key == null) throw new IllegalArgumentException(\"calls get() with a null key\");\n        if (node == null) return null;\n        int cmp = key.compareTo(node.key);\n        if      (cmp < 0) return get(node.left, key);\n        else if (cmp > 0) return get(node.right, key);\n        else              return node.val;\n    }\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"calls put() with a null key\");\n        if (val == null) {\n            delete(key);\n            return;\n        }\n        root = put(root, key, val);\n        assert check();\n    }\n\n    private Node put(Node node, Key key, Value val) {\n        if (node == null) return new Node(key, val, 1);\n        int cmp = key.compareTo(node.key);\n        if      (cmp < 0) node.left  = put(node.left,  key, val);\n        else if (cmp > 0) node.right = put(node.right, key, val);\n        else              node.val   = val;\n        node.size = 1 + size(node.left) + size(node.right);\n        return node;\n    }\n\n\n    /**\n     * Removes the smallest key and associated value from the symbol table.\n     *\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMin() {\n        if (isEmpty()) throw new NoSuchElementException(\"Symbol table underflow\");\n        root = deleteMin(root);\n        assert check();\n    }\n\n    private Node deleteMin(Node node) {\n        if (node.left == null) return node.right;\n        node.left = deleteMin(node.left);\n        node.size = size(node.left) + size(node.right) + 1;\n        return node;\n    }\n\n    /**\n     * Removes the largest key and associated value from the symbol table.\n     *\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMax() {\n        if (isEmpty()) throw new NoSuchElementException(\"Symbol table underflow\");\n        root = deleteMax(root);\n        assert check();\n    }\n\n    private Node deleteMax(Node node) {\n        if (node.right == null) return node.left;\n        node.right = deleteMax(node.right);\n        node.size = size(node.left) + size(node.right) + 1;\n        return node;\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"calls delete() with a null key\");\n        root = delete(root, key);\n        assert check();\n    }\n\n    private Node delete(Node node, Key key) {\n        if (node == null) return null;\n\n        int cmp = key.compareTo(node.key);\n        if      (cmp < 0) node.left  = delete(node.left,  key);\n        else if (cmp > 0) node.right = delete(node.right, key);\n        else {\n            if (node.right == null) return node.left;\n            if (node.left  == null) return node.right;\n            Node temp = node;\n            node = min(temp.right);\n            node.right = deleteMin(temp.right);\n            node.left = temp.left;\n        }\n        node.size = size(node.left) + size(node.right) + 1;\n        return node;\n    }\n\n\n    /**\n     * Returns the smallest key in the symbol table.\n     *\n     * @return the smallest key in the symbol table\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"calls min() with empty symbol table\");\n        return min(root).key;\n    }\n\n    private Node min(Node node) {\n        if (node.left == null) return node;\n        else                   return min(node.left);\n    }\n\n    /**\n     * Returns the largest key in the symbol table.\n     *\n     * @return the largest key in the symbol table\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"calls max() with empty symbol table\");\n        return max(root).key;\n    }\n\n    private Node max(Node node) {\n        if (node.right == null) return node;\n        else                    return max(node.right);\n    }\n\n    /**\n     * Returns the largest key in the symbol table less than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the largest key in the symbol table less than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key floor(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to floor() is null\");\n        if (isEmpty()) throw new NoSuchElementException(\"calls floor() with empty symbol table\");\n        Node node = floor(root, key);\n        if (node == null) throw new NoSuchElementException(\"argument to floor() is too small\");\n        else return node.key;\n    }\n\n    private Node floor(Node node, Key key) {\n        if (node == null) return null;\n        int cmp = key.compareTo(node.key);\n        if (cmp == 0) return node;\n        if (cmp <  0) return floor(node.left, key);\n        Node t = floor(node.right, key);\n        if (t != null) return t;\n        else return node;\n    }\n\n    public Key floor2(Key key) {\n        Key floor = floor2(root, key, null);\n        if (floor == null) throw new NoSuchElementException(\"argument to floor() is too small\");\n        else return floor;\n\n    }\n\n    private Key floor2(Node node, Key key, Key champ) {\n        if (node == null) return champ;\n        int cmp = key.compareTo(node.key);\n        if      (cmp  < 0) return floor2(node.left, key, champ);\n        else if (cmp  > 0) return floor2(node.right, key, node.key);\n        else               return node.key;\n    }\n\n    /**\n     * Returns the smallest key in the symbol table greater than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the smallest key in the symbol table greater than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key ceiling(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to ceiling() is null\");\n        if (isEmpty()) throw new NoSuchElementException(\"calls ceiling() with empty symbol table\");\n        Node node = ceiling(root, key);\n        if (node == null) throw new NoSuchElementException(\"argument to ceiling() is too large\");\n        else return node.key;\n    }\n\n    private Node ceiling(Node node, Key key) {\n        if (node == null) return null;\n        int cmp = key.compareTo(node.key);\n        if (cmp == 0) return node;\n        if (cmp < 0) {\n            Node t = ceiling(node.left, key);\n            if (t != null) return t;\n            else return node;\n        }\n        return ceiling(node.right, key);\n    }\n\n    /**\n     * Return the key in the symbol table of a given {@code rank}.\n     * This key has the property that there are {@code rank} keys in\n     * the symbol table that are smaller. In other words, this key is the\n     * ({@code rank}+1)st smallest key in the symbol table.\n     *\n     * @param  rank the order statistic\n     * @return the key in the symbol table of given {@code rank}\n     * @throws IllegalArgumentException unless {@code rank} is between 0 and\n     *        <em>n</em>–1\n     */\n    public Key select(int rank) {\n        if (rank < 0 || rank >= size()) {\n            throw new IllegalArgumentException(\"argument to select() is invalid: \" + rank);\n        }\n        return select(root, rank);\n    }\n\n    // Return key in BST rooted at x of given rank.\n    // Precondition: rank is in legal range.\n    private Key select(Node node, int rank) {\n        if (node == null) return null;\n        int leftSize = size(node.left);\n        if      (leftSize > rank) return select(node.left,  rank);\n        else if (leftSize < rank) return select(node.right, rank - leftSize - 1);\n        else                      return node.key;\n    }\n\n    /**\n     * Return the number of keys in the symbol table strictly less than {@code key}.\n     *\n     * @param  key the key\n     * @return the number of keys in the symbol table strictly less than {@code key}\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public int rank(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to rank() is null\");\n        return rank(key, root);\n    }\n\n    // Number of keys in the subtree less than key.\n    private int rank(Key key, Node node) {\n        if (node == null) return 0;\n        int cmp = key.compareTo(node.key);\n        if      (cmp < 0) return rank(key, node.left);\n        else if (cmp > 0) return 1 + size(node.left) + rank(key, node.right);\n        else              return size(node.left);\n    }\n\n    /**\n     * Returns all keys in the symbol table in ascending order,\n     * as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     *\n     * @return all keys in the symbol table in ascending order\n     */\n    public Iterable<Key> keys() {\n        if (isEmpty()) return new Queue<Key>();\n        return keys(min(), max());\n    }\n\n    /**\n     * Returns all keys in the symbol table in the given range\n     * in ascending order, as an {@code Iterable}.\n     *\n     * @param  lo minimum endpoint\n     * @param  hi maximum endpoint\n     * @return all keys in the symbol table between {@code lo}\n     *         (inclusive) and {@code hi} (inclusive) in ascending order\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *         is {@code null}\n     */\n    public Iterable<Key> keys(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to keys() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to keys() is null\");\n\n        Queue<Key> queue = new Queue<Key>();\n        keys(root, queue, lo, hi);\n        return queue;\n    }\n\n    private void keys(Node node, Queue<Key> queue, Key lo, Key hi) {\n        if (node == null) return;\n        int cmplo = lo.compareTo(node.key);\n        int cmphi = hi.compareTo(node.key);\n        if (cmplo < 0) keys(node.left, queue, lo, hi);\n        if (cmplo <= 0 && cmphi >= 0) queue.enqueue(node.key);\n        if (cmphi > 0) keys(node.right, queue, lo, hi);\n    }\n\n    /**\n     * Returns the number of keys in the symbol table in the given range.\n     *\n     * @param  lo minimum endpoint\n     * @param  hi maximum endpoint\n     * @return the number of keys in the symbol table between {@code lo}\n     *         (inclusive) and {@code hi} (inclusive)\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *         is {@code null}\n     */\n    public int size(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to size() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to size() is null\");\n\n        if (lo.compareTo(hi) > 0) return 0;\n        if (contains(hi)) return rank(hi) - rank(lo) + 1;\n        else              return rank(hi) - rank(lo);\n    }\n\n    /**\n     * Returns the height of the BST (for debugging).\n     *\n     * @return the height of the BST (a 1-node tree has height 0)\n     */\n    public int height() {\n        return height(root);\n    }\n    private int height(Node node) {\n        if (node == null) return -1;\n        return 1 + Math.max(height(node.left), height(node.right));\n    }\n\n    /**\n     * Returns the keys in the BST in level order (for debugging).\n     *\n     * @return the keys in the BST in level order traversal\n     */\n    public Iterable<Key> levelOrder() {\n        Queue<Key> keys = new Queue<Key>();\n        Queue<Node> queue = new Queue<Node>();\n        queue.enqueue(root);\n        while (!queue.isEmpty()) {\n            Node node = queue.dequeue();\n            if (node == null) continue;\n            keys.enqueue(node.key);\n            queue.enqueue(node.left);\n            queue.enqueue(node.right);\n        }\n        return keys;\n    }\n\n  /*************************************************************************\n    *  Check integrity of BST data structure.\n    ***************************************************************************/\n    private boolean check() {\n        if (!isBST())            StdOut.println(\"Not in symmetric order\");\n        if (!isSizeConsistent()) StdOut.println(\"Subtree counts not consistent\");\n        if (!isRankConsistent()) StdOut.println(\"Ranks not consistent\");\n        return isBST() && isSizeConsistent() && isRankConsistent();\n    }\n\n    // does this binary tree satisfy symmetric order?\n    // Note: this test also ensures that data structure is a binary tree since order is strict\n    private boolean isBST() {\n        return isBST(root, null, null);\n    }\n\n    // is the tree rooted at x a BST with all keys strictly between min and max\n    // (if min or max is null, treat as empty constraint)\n    // Credit: elegant solution due to Bob Dondero\n    private boolean isBST(Node node, Key min, Key max) {\n        if (node == null) return true;\n        if (min != null && node.key.compareTo(min) <= 0) return false;\n        if (max != null && node.key.compareTo(max) >= 0) return false;\n        return isBST(node.left, min, node.key) && isBST(node.right, node.key, max);\n    }\n\n    // are the size fields correct?\n    private boolean isSizeConsistent() { return isSizeConsistent(root); }\n    private boolean isSizeConsistent(Node node) {\n        if (node == null) return true;\n        if (node.size != size(node.left) + size(node.right) + 1) return false;\n        return isSizeConsistent(node.left) && isSizeConsistent(node.right);\n    }\n\n    // check that ranks are consistent\n    private boolean isRankConsistent() {\n        for (int i = 0; i < size(); i++)\n            if (i != rank(select(i))) return false;\n        for (Key key : keys())\n            if (key.compareTo(select(rank(key))) != 0) return false;\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code BST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        BST<String, Integer> st = new BST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n\n        for (String s : st.levelOrder())\n            StdOut.println(s + \" \" + st.get(s));\n\n        StdOut.println();\n\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BTree.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BTree.java\n *  Execution:    java BTree\n *  Dependencies: StdOut.java\n *\n *  B-tree.\n *\n *  Limitations\n *  -----------\n *   -  Assumes M is even and M >= 4\n *   -  should b be an array of children or list (it would help with\n *      casting to make it a list)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BTree} class represents an ordered symbol table of generic\n *  key-value pairs.\n *  It supports the <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>size</em>, and <em>is-empty</em> methods.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  This implementation uses a B-tree. It requires that\n *  the key type implements the {@code Comparable} interface and calls the\n *  {@code compareTo()} and method to compare two keys. It does not call either\n *  {@code equals()} or {@code hashCode()}.\n *  The <em>get</em>, <em>put</em>, and <em>contains</em> operations\n *  each make log<sub><em>m</em></sub>(<em>n</em>) probes in the worst case,\n *  where <em>n</em> is the number of key-value pairs\n *  and <em>m</em> is the branching factor.\n *  The <em>size</em>, and <em>is-empty</em> operations take constant time.\n *  Construction takes constant time.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/62btree\">Section 6.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class BTree<Key extends Comparable<Key>, Value>  {\n    // max children per B-tree node = M-1\n    // (must be even and greater than 2)\n    private static final int M = 4;\n\n    private Node root;       // root of the B-tree\n    private int height;      // height of the B-tree\n    private int n;           // number of key-value pairs in the B-tree\n\n    // helper B-tree node data type\n    private static final class Node {\n        private int m;                             // number of children\n        private Entry[] children = new Entry[M];   // the array of children\n\n        // create a node with k children\n        private Node(int k) {\n            m = k;\n        }\n    }\n\n    // internal nodes: only use key and next\n    // external nodes: only use key and value\n    private static class Entry {\n        private Comparable key;\n        private Object val;\n        private Node next;     // helper field to iterate over array entries\n        public Entry(Comparable key, Object val, Node next) {\n            this.key  = key;\n            this.val  = val;\n            this.next = next;\n        }\n    }\n\n    /**\n     * Initializes an empty B-tree.\n     */\n    public BTree() {\n        root = new Node(0);\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     * @return {@code true} if this symbol table is empty; {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns the height of this B-tree (for debugging).\n     *\n     * @return the height of this B-tree\n     */\n    public int height() {\n        return height;\n    }\n\n\n    /**\n     * Returns the value associated with the given key.\n     *\n     * @param  key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *         and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        return search(root, key, height);\n    }\n\n    private Value search(Node x, Key key, int ht) {\n        Entry[] children = x.children;\n\n        // external node\n        if (ht == 0) {\n            for (int j = 0; j < x.m; j++) {\n                if (eq(key, children[j].key)) return (Value) children[j].val;\n            }\n        }\n\n        // internal node\n        else {\n            for (int j = 0; j < x.m; j++) {\n                if (j+1 == x.m || less(key, children[j+1].key))\n                    return search(children[j].next, key, ht-1);\n            }\n        }\n        return null;\n    }\n\n\n    /**\n     * Inserts the key-value pair into the symbol table, overwriting the old value\n     * with the new value if the key is already in the symbol table.\n     * If the value is {@code null}, this effectively deletes the key from the symbol table.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"argument key to put() is null\");\n        Node u = insert(root, key, val, height);\n        n++;\n        if (u == null) return;\n\n        // need to split root\n        Node t = new Node(2);\n        t.children[0] = new Entry(root.children[0].key, null, root);\n        t.children[1] = new Entry(u.children[0].key, null, u);\n        root = t;\n        height++;\n    }\n\n    private Node insert(Node h, Key key, Value val, int ht) {\n        int j;\n        Entry t = new Entry(key, val, null);\n\n        // external node\n        if (ht == 0) {\n            for (j = 0; j < h.m; j++) {\n                if (less(key, h.children[j].key)) break;\n            }\n        }\n\n        // internal node\n        else {\n            for (j = 0; j < h.m; j++) {\n                if ((j+1 == h.m) || less(key, h.children[j+1].key)) {\n                    Node u = insert(h.children[j++].next, key, val, ht-1);\n                    if (u == null) return null;\n                    t.key = u.children[0].key;\n                    t.val = null;\n                    t.next = u;\n                    break;\n                }\n            }\n        }\n\n        for (int i = h.m; i > j; i--)\n            h.children[i] = h.children[i-1];\n        h.children[j] = t;\n        h.m++;\n        if (h.m < M) return null;\n        else         return split(h);\n    }\n\n    // split node in half\n    private Node split(Node h) {\n        Node t = new Node(M/2);\n        h.m = M/2;\n        for (int j = 0; j < M/2; j++)\n            t.children[j] = h.children[M/2+j];\n        return t;\n    }\n\n    /**\n     * Returns a string representation of this B-tree (for debugging).\n     *\n     * @return a string representation of this B-tree.\n     */\n    public String toString() {\n        return toString(root, height, \"\") + \"\\n\";\n    }\n\n    private String toString(Node h, int ht, String indent) {\n        StringBuilder s = new StringBuilder();\n        Entry[] children = h.children;\n\n        if (ht == 0) {\n            for (int j = 0; j < h.m; j++) {\n                s.append(indent + children[j].key + \" \" + children[j].val + \"\\n\");\n            }\n        }\n        else {\n            for (int j = 0; j < h.m; j++) {\n                if (j > 0) s.append(indent + \"(\" + children[j].key + \")\\n\");\n                s.append(toString(children[j].next, ht-1, indent + \"     \"));\n            }\n        }\n        return s.toString();\n    }\n\n\n    // comparison functions - make Comparable instead of Key to avoid casts\n    private boolean less(Comparable k1, Comparable k2) {\n        return k1.compareTo(k2) < 0;\n    }\n\n    private boolean eq(Comparable k1, Comparable k2) {\n        return k1.compareTo(k2) == 0;\n    }\n\n\n    /**\n     * Unit tests the {@code BTree} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        BTree<String, String> st = new BTree<String, String>();\n\n        st.put(\"www.cs.princeton.edu\", \"128.112.136.12\");\n        st.put(\"www.cs.princeton.edu\", \"128.112.136.11\");\n        st.put(\"www.princeton.edu\",    \"128.112.128.15\");\n        st.put(\"www.yale.edu\",         \"130.132.143.21\");\n        st.put(\"www.simpsons.com\",     \"209.052.165.60\");\n        st.put(\"www.apple.com\",        \"17.112.152.32\");\n        st.put(\"www.amazon.com\",       \"207.171.182.16\");\n        st.put(\"www.ebay.com\",         \"66.135.192.87\");\n        st.put(\"www.cnn.com\",          \"64.236.16.20\");\n        st.put(\"www.google.com\",       \"216.239.41.99\");\n        st.put(\"www.nytimes.com\",      \"199.239.136.200\");\n        st.put(\"www.microsoft.com\",    \"207.126.99.140\");\n        st.put(\"www.dell.com\",         \"143.166.224.230\");\n        st.put(\"www.slashdot.org\",     \"66.35.250.151\");\n        st.put(\"www.espn.com\",         \"199.181.135.201\");\n        st.put(\"www.weather.com\",      \"63.111.66.11\");\n        st.put(\"www.yahoo.com\",        \"216.109.118.65\");\n\n\n        StdOut.println(\"cs.princeton.edu:  \" + st.get(\"www.cs.princeton.edu\"));\n        StdOut.println(\"hardvardsucks.com: \" + st.get(\"www.harvardsucks.com\"));\n        StdOut.println(\"simpsons.com:      \" + st.get(\"www.simpsons.com\"));\n        StdOut.println(\"apple.com:         \" + st.get(\"www.apple.com\"));\n        StdOut.println(\"ebay.com:          \" + st.get(\"www.ebay.com\"));\n        StdOut.println(\"dell.com:          \" + st.get(\"www.dell.com\"));\n        StdOut.println();\n\n        StdOut.println(\"size:    \" + st.size());\n        StdOut.println(\"height:  \" + st.height());\n        StdOut.println(st);\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Bag.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Bag.java\n *  Execution:    java Bag < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *\n *  A generic bag or multiset, implemented using a singly linked list.\n *\n *  % more tobe.txt\n *  to be or not to - be - - that - - - is\n *\n *  % java Bag < tobe.txt\n *  size of bag = 14\n *  is\n *  -\n *  -\n *  -\n *  that\n *  -\n *  -\n *  be\n *  -\n *  to\n *  not\n *  or\n *  be\n *  to\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code Bag} class represents a bag (or multiset) of\n *  generic items. It supports insertion and iterating over the\n *  items in arbitrary order.\n *  <p>\n *  This implementation uses a singly linked list with a static nested class Node.\n *  See {@link LinkedBag} for the version from the\n *  textbook that uses a non-static nested class.\n *  See {@link ResizingArrayBag} for a version that uses a resizing array.\n *  The <em>add</em>, <em>isEmpty</em>, and <em>size</em> operations\n *  take constant time. Iteration takes time proportional to the number of items.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Item> the generic type of each item in this bag\n */\npublic class Bag<Item> implements Iterable<Item> {\n    private Node<Item> first;    // beginning of bag\n    private int n;               // number of elements in bag\n\n    // helper linked list class\n    private static class Node<Item> {\n        private Item item;\n        private Node<Item> next;\n    }\n\n    /**\n     * Initializes an empty bag.\n     */\n    public Bag() {\n        first = null;\n        n = 0;\n    }\n\n    /**\n     * Returns true if this bag is empty.\n     *\n     * @return {@code true} if this bag is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return first == null;\n    }\n\n    /**\n     * Returns the number of items in this bag.\n     *\n     * @return the number of items in this bag\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Adds the item to this bag.\n     *\n     * @param  item the item to add to this bag\n     */\n    public void add(Item item) {\n        Node<Item> oldfirst = first;\n        first = new Node<Item>();\n        first.item = item;\n        first.next = oldfirst;\n        n++;\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the items in this bag in arbitrary order.\n     *\n     * @return an iterator that iterates over the items in this bag in arbitrary order\n     */\n    public Iterator<Item> iterator()  {\n        return new LinkedIterator(first);\n    }\n\n    private class LinkedIterator implements Iterator<Item> {\n        private Node<Item> current;\n\n        public LinkedIterator(Node<Item> first) {\n            current = first;\n        }\n\n        public boolean hasNext()  {\n            return current != null;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = current.item;\n            current = current.next;\n            return item;\n        }\n    }\n\n    /**\n     * Unit tests the {@code Bag} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Bag<String> bag = new Bag<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            bag.add(item);\n        }\n\n        StdOut.println(\"size of bag = \" + bag.size());\n        for (String s : bag) {\n            StdOut.println(s);\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BellmanFordSP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BellmanFordSP.java\n *  Execution:    java BellmanFordSP filename.txt s\n *  Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Queue.java\n *                EdgeWeightedDirectedCycle.java\n *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWDn.txt\n *                https://algs4.cs.princeton.edu/44sp/tinyEWDnc.txt\n *                https://algs4.cs.princeton.edu/44sp/mediumEWD.txt\n *                https://algs4.cs.princeton.edu/44sp/largeEWD.txt\n *\n *  Bellman-Ford shortest path algorithm. Computes the shortest path tree in\n *  edge-weighted digraph G from vertex s, or finds a negative cost cycle\n *  reachable from s.\n *\n *  % java BellmanFordSP tinyEWDn.txt 0\n *  0 to 0 ( 0.00)\n *  0 to 1 ( 0.93)  0->2  0.26   2->7  0.34   7->3  0.39   3->6  0.52   6->4 -1.25   4->5  0.35   5->1  0.32\n *  0 to 2 ( 0.26)  0->2  0.26\n *  0 to 3 ( 0.99)  0->2  0.26   2->7  0.34   7->3  0.39\n *  0 to 4 ( 0.26)  0->2  0.26   2->7  0.34   7->3  0.39   3->6  0.52   6->4 -1.25\n *  0 to 5 ( 0.61)  0->2  0.26   2->7  0.34   7->3  0.39   3->6  0.52   6->4 -1.25   4->5  0.35\n *  0 to 6 ( 1.51)  0->2  0.26   2->7  0.34   7->3  0.39   3->6  0.52\n *  0 to 7 ( 0.60)  0->2  0.26   2->7  0.34\n *\n *  % java BellmanFordSP tinyEWDnc.txt 0\n *  4->5  0.35\n *  5->4 -0.66\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BellmanFordSP} class represents a data type for solving the\n *  single-source shortest paths problem in edge-weighted digraphs with\n *  no negative cycles.\n *  The edge weights can be positive, negative, or zero.\n *  This class finds either a shortest path from the source vertex <em>s</em>\n *  to every other vertex or a negative cycle reachable from the source vertex.\n *  <p>\n *  This implementation uses a queue-based implementation of\n *  the Bellman-Ford-Moore algorithm.\n *  The constructor takes &Theta;(<em>E</em> <em>V</em>) time\n *  in the worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges. In practice, it performs much better.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted digraph).\n *  <p>\n *  This correctly computes shortest paths if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>. Since all intermediate\n *  results are sums of edge weights, they are bounded by <em>V C</em>,\n *  where <em>V</em> is the number of vertices and <em>C</em> is the maximum\n *  absolute value of any edge weight.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BellmanFordSP {\n    // for floating-point precision issues\n    private static final double EPSILON = 1E-14;\n\n    private double[] distTo;               // distTo[v] = distance  of shortest s->v path\n    private DirectedEdge[] edgeTo;         // edgeTo[v] = last edge on shortest s->v path\n    private boolean[] onQueue;             // onQueue[v] = is v currently on the queue?\n    private Queue<Integer> queue;          // queue of vertices to relax\n    private int cost;                      // number of calls to relax()\n    private Iterable<DirectedEdge> cycle;  // negative cycle (or null if no such cycle)\n\n    /**\n     * Computes a shortest paths tree from {@code s} to every other vertex in\n     * the edge-weighted {@code digraph}.\n     * @param digraph the acyclic digraph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public BellmanFordSP(EdgeWeightedDigraph digraph, int s) {\n        distTo  = new double[digraph.V()];\n        edgeTo  = new DirectedEdge[digraph.V()];\n        onQueue = new boolean[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            distTo[v] = Double.POSITIVE_INFINITY;\n        distTo[s] = 0.0;\n\n        // Bellman-Ford algorithm\n        queue = new Queue<Integer>();\n        queue.enqueue(s);\n        onQueue[s] = true;\n        while (!queue.isEmpty() && !hasNegativeCycle()) {\n            int v = queue.dequeue();\n            onQueue[v] = false;\n            relax(digraph, v);\n        }\n\n        assert check(digraph, s);\n    }\n\n    // relax vertex v and put other endpoints on queue if changed\n    private void relax(EdgeWeightedDigraph digraph, int v) {\n        for (DirectedEdge e : digraph.adj(v)) {\n            int w = e.to();\n            if (distTo[w] > distTo[v] + e.weight() + EPSILON) {\n                distTo[w] = distTo[v] + e.weight();\n                edgeTo[w] = e;\n                if (!onQueue[w]) {\n                    queue.enqueue(w);\n                    onQueue[w] = true;\n                }\n            }\n            if (++cost % digraph.V() == 0) {\n                findNegativeCycle();\n                if (hasNegativeCycle()) return;  // found a negative cycle\n            }\n        }\n    }\n\n    /**\n     * Is there a negative cycle reachable from the source vertex {@code s}?\n     * @return {@code true} if there is a negative cycle reachable from the\n     *    source vertex {@code s}, and {@code false} otherwise\n     */\n    public boolean hasNegativeCycle() {\n        return cycle != null;\n    }\n\n    /**\n     * Returns a negative cycle reachable from the source vertex {@code s}, or {@code null}\n     * if there is no such cycle.\n     * @return a negative cycle reachable from the source vertex {@code s}\n     *    as an iterable of edges, and {@code null} if there is no such cycle\n     */\n    public Iterable<DirectedEdge> negativeCycle() {\n        return cycle;\n    }\n\n    // by finding a cycle in predecessor graph\n    private void findNegativeCycle() {\n        int V = edgeTo.length;\n        EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V);\n        for (int v = 0; v < V; v++)\n            if (edgeTo[v] != null)\n                spt.addEdge(edgeTo[v]);\n\n        EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt);\n        cycle = finder.cycle();\n    }\n\n    /**\n     * Returns the length of a shortest path from the source vertex {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return the length of a shortest path from the source vertex {@code s} to vertex {@code v};\n     *         {@code Double.POSITIVE_INFINITY} if no such path\n     * @throws UnsupportedOperationException if there is a negative cost cycle reachable\n     *         from the source vertex {@code s}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public double distTo(int v) {\n        validateVertex(v);\n        if (hasNegativeCycle())\n            throw new UnsupportedOperationException(\"Negative cost cycle exists\");\n        return distTo[v];\n    }\n\n    /**\n     * Is there a path from the source {@code s} to vertex {@code v}?\n     * @param  v the destination vertex\n     * @return {@code true} if there is a path from the source vertex\n     *         {@code s} to vertex {@code v}, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return distTo[v] < Double.POSITIVE_INFINITY;\n    }\n\n    /**\n     * Returns a shortest path from the source {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return a shortest path from the source {@code s} to vertex {@code v}\n     *         as an iterable of edges, and {@code null} if no such path\n     * @throws UnsupportedOperationException if there is a negative cost cycle reachable\n     *         from the source vertex {@code s}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> pathTo(int v) {\n        validateVertex(v);\n        if (hasNegativeCycle())\n            throw new UnsupportedOperationException(\"Negative cost cycle exists\");\n        if (!hasPathTo(v)) return null;\n        Stack<DirectedEdge> path = new Stack<DirectedEdge>();\n        for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {\n            path.push(e);\n        }\n        return path;\n    }\n\n    // check optimality conditions: either\n    // (i) there exists a negative cycle reachable from s\n    //     or\n    // (ii)  for all edges e = v->w:            distTo[w] <= distTo[v] + e.weight()\n    // (ii') for all edges e = v->w on the SPT: distTo[w] == distTo[v] + e.weight()\n    private boolean check(EdgeWeightedDigraph digraph, int s) {\n\n        // has a negative cycle\n        if (hasNegativeCycle()) {\n            double weight = 0.0;\n            for (DirectedEdge e : negativeCycle()) {\n                weight += e.weight();\n            }\n            if (weight >= 0.0) {\n                System.err.println(\"error: weight of negative cycle = \" + weight);\n                return false;\n            }\n        }\n\n        // no negative cycle reachable from source\n        else {\n\n            // check that distTo[v] and edgeTo[v] are consistent\n            if (distTo[s] != 0.0 || edgeTo[s] != null) {\n                System.err.println(\"distanceTo[s] and edgeTo[s] inconsistent\");\n                return false;\n            }\n            for (int v = 0; v < digraph.V(); v++) {\n                if (v == s) continue;\n                if (edgeTo[v] == null && distTo[v] != Double.POSITIVE_INFINITY) {\n                    System.err.println(\"distTo[] and edgeTo[] inconsistent\");\n                    return false;\n                }\n            }\n\n            // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()\n            for (int v = 0; v < digraph.V(); v++) {\n                for (DirectedEdge e : digraph.adj(v)) {\n                    int w = e.to();\n                    if (distTo[v] + e.weight() < distTo[w]) {\n                        System.err.println(\"edge \" + e + \" not relaxed\");\n                        return false;\n                    }\n                }\n            }\n\n            // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()\n            for (int w = 0; w < digraph.V(); w++) {\n                if (edgeTo[w] == null) continue;\n                DirectedEdge e = edgeTo[w];\n                int v = e.from();\n                if (w != e.to()) return false;\n                if (distTo[v] + e.weight() != distTo[w]) {\n                    System.err.println(\"edge \" + e + \" on shortest path not tight\");\n                    return false;\n                }\n            }\n        }\n\n        StdOut.println(\"Satisfies optimality conditions\");\n        StdOut.println();\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = distTo.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code BellmanFordSP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        int s = Integer.parseInt(args[1]);\n        EdgeWeightedDigraph digraph = new EdgeWeightedDigraph(in);\n\n        BellmanFordSP sp = new BellmanFordSP(digraph, s);\n\n        // print negative cycle\n        if (sp.hasNegativeCycle()) {\n            for (DirectedEdge e : sp.negativeCycle())\n                StdOut.println(e);\n        }\n\n        // print shortest paths\n        else {\n            for (int v = 0; v < digraph.V(); v++) {\n                if (sp.hasPathTo(v)) {\n                    StdOut.printf(\"%d to %d (%5.2f)  \", s, v, sp.distTo(v));\n                    for (DirectedEdge e : sp.pathTo(v)) {\n                        StdOut.print(e + \"   \");\n                    }\n                    StdOut.println();\n                }\n                else {\n                    StdOut.printf(\"%d to %d           no path\\n\", s, v);\n                }\n            }\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinaryDump.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinaryDump.java\n *  Execution:    java BinaryDump n < file\n *  Dependencies: BinaryStdIn.java\n *  Data file:    https://introcs.cs.princeton.edu/stdlib/abra.txt\n *\n *  Reads in a binary file and writes out the bits, n per line.\n *\n *  % more abra.txt\n *  ABRACADABRA!\n *\n *  % java BinaryDump 16 < abra.txt\n *  0100000101000010\n *  0101001001000001\n *  0100001101000001\n *  0100010001000001\n *  0100001001010010\n *  0100000100100001\n *  96 bits\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BinaryDump} class provides a client for displaying the contents\n *  of a binary file in binary.\n *  <p>\n *  For more full-featured versions, see the Unix utilities\n *  {@code od} (octal dump) and {@code hexdump} (hexadecimal dump).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  <p>\n *  See also {@link HexDump} and {@link PictureDump}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BinaryDump {\n\n    // Do not instantiate.\n    private BinaryDump() { }\n\n    /**\n     * Reads in a sequence of bytes from standard input and writes\n     * them to standard output in binary, k bits per line,\n     * where k is given as a command-line integer (defaults\n     * to 16 if no integer is specified); also writes the number\n     * of bits.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int bitsPerLine = 16;\n        if (args.length == 1) {\n            bitsPerLine = Integer.parseInt(args[0]);\n        }\n\n        int count;\n        for (count = 0; !BinaryStdIn.isEmpty(); count++) {\n            if (bitsPerLine == 0) {\n                BinaryStdIn.readBoolean();\n                continue;\n            }\n            else if (count != 0 && count % bitsPerLine == 0) StdOut.println();\n            if (BinaryStdIn.readBoolean()) StdOut.print(1);\n            else                           StdOut.print(0);\n        }\n        if (bitsPerLine != 0) StdOut.println();\n        StdOut.println(count + \" bits\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinaryIn.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinaryIn.java\n *  Execution:    java BinaryIn input output\n *  Dependencies: none\n *\n *  This library is for reading binary data from an input stream.\n *\n *  % java BinaryIn https://introcs.cs.princeton.edu/java/cover.png output.png\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.BufferedInputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.Socket;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.net.URLConnection;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The <code>BinaryIn</code> data type provides methods for reading\n *  in bits from a binary input stream. It can process the bits\n *  one bit at a time (as a {@code boolean}),\n *  8 bits at a time (as a {@code byte} or {@code char}),\n *  16 bits at a time (as a {@code short}),\n *  32 bits at a time (as an {@code int} or {@code float}), or\n *  64 bits at a time (as a {@code double} or {@code long}).\n *  <p>\n *  The binary input stream can be from standard input, a filename,\n *  a URL name, a Socket, or an InputStream.\n *  <p>\n *  All primitive types are assumed to be represented using their\n *  standard Java representations, in big-endian (most significant\n *  byte first) order.\n *  <p>\n *  The client should not intermix calls to {@code BinaryIn} with calls\n *  to {@code In}; otherwise unexpected behavior will result.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class BinaryIn {\n    private static final int EOF = -1;   // end of file\n\n    private BufferedInputStream in;      // the input stream\n    private int buffer;                  // one character buffer\n    private int n;                       // number of bits left in buffer\n\n   /**\n     * Initializes a binary input stream from standard input.\n     */\n    public BinaryIn() {\n        in = new BufferedInputStream(System.in);\n        fillBuffer();\n    }\n\n   /**\n     * Initializes a binary input stream from an {@code InputStream}.\n     *\n     * @param is the {@code InputStream} object\n     */\n    public BinaryIn(InputStream is) {\n        in = new BufferedInputStream(is);\n        fillBuffer();\n    }\n\n   /**\n     * Initializes a binary input stream from a socket.\n     *\n     * @param socket the socket\n     */\n    public BinaryIn(Socket socket) {\n        try {\n            InputStream is = socket.getInputStream();\n            in = new BufferedInputStream(is);\n            fillBuffer();\n        }\n        catch (IOException ioe) {\n            System.err.println(\"could not read socket: \" + socket);\n        }\n    }\n\n   /**\n     * Initializes a binary input stream from a URL.\n     *\n     * @param url the URL\n     */\n    public BinaryIn(URL url) {\n        try {\n            URLConnection site = url.openConnection();\n            InputStream is     = site.getInputStream();\n            in = new BufferedInputStream(is);\n            fillBuffer();\n        }\n        catch (IOException ioe) {\n            System.err.println(\"could not open URL: '\" + url + \"'\");\n        }\n    }\n\n   /**\n     * Initializes a binary input stream from a filename or URL name.\n     *\n     * @param name the name of the file or URL\n     */\n    public BinaryIn(String name) {\n\n        try {\n            // first try to read file from local file system\n            File file = new File(name);\n            if (file.exists()) {\n                FileInputStream fis = new FileInputStream(file);\n                in = new BufferedInputStream(fis);\n                fillBuffer();\n                return;\n            }\n\n            // next try for files included in jar\n            URL url = getClass().getResource(name);\n\n            // or URL from web\n            if (url == null) {\n                URI uri = new URI(name);\n                if (uri.isAbsolute()) url = uri.toURL();\n                else throw new IllegalArgumentException(\"could not read: '\" + name+ \"'\");\n            }\n\n            URLConnection site = url.openConnection();\n            InputStream is     = site.getInputStream();\n            in = new BufferedInputStream(is);\n            fillBuffer();\n        }\n        catch (IOException | URISyntaxException e) {\n            System.err.println(\"could not open: '\" + name + \"'\");\n        }\n    }\n\n    private void fillBuffer() {\n        try {\n            buffer = in.read();\n            n = 8;\n        }\n        catch (IOException e) {\n            System.err.println(\"EOF\");\n            buffer = EOF;\n            n = -1;\n        }\n    }\n\n    /**\n     * Returns true if this binary input stream exists.\n     *\n     * @return {@code true} if this binary input stream exists;\n     *         {@code false} otherwise\n     */\n    public boolean exists()  {\n        return in != null;\n    }\n\n   /**\n     * Returns true if this binary input stream is empty.\n     *\n     * @return {@code true} if this binary input stream is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return buffer == EOF;\n    }\n\n   /**\n     * Reads the next bit of data from this binary input stream and return as a boolean.\n     *\n     * @return the next bit of data from this binary input stream as a {@code boolean}\n     * @throws NoSuchElementException if this binary input stream is empty\n     */\n    public boolean readBoolean() {\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n        n--;\n        boolean bit = ((buffer >> n) & 1) == 1;\n        if (n == 0) fillBuffer();\n        return bit;\n    }\n\n   /**\n     * Reads the next 8 bits from this binary input stream and return as an 8-bit char.\n     *\n     * @return the next 8 bits of data from this binary input stream as a {@code char}\n     * @throws NoSuchElementException if there are fewer than 8 bits available\n     */\n    public char readChar() {\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n\n        // special case when aligned byte\n        if (n == 8) {\n            int x = buffer;\n            fillBuffer();\n            return (char) (x & 0xff);\n        }\n\n        // combine last N bits of current buffer with first 8-N bits of new buffer\n        int x = buffer;\n        x <<= (8 - n);\n        int oldN = n;\n        fillBuffer();\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n        n = oldN;\n        x |= (buffer >>> n);\n        return (char) (x & 0xff);\n        // the above code doesn't quite work for the last character if N = 8\n        // because buffer will be -1\n    }\n\n\n   /**\n     * Reads the next <em>r</em> bits from this binary input stream and return\n     * as an <em>r</em>-bit character.\n     *\n     * @param  r number of bits to read\n     * @return the next {@code r} bits of data from this binary input stream as a {@code char}\n     * @throws NoSuchElementException if there are fewer than {@code r} bits available\n     * @throws IllegalArgumentException unless {@code 1 <= r <= 16}\n     */\n    public char readChar(int r) {\n        if (r < 1 || r > 16) throw new IllegalArgumentException(\"Illegal value of r = \" + r);\n\n        // optimize r = 8 case\n        if (r == 8) return readChar();\n\n        char x = 0;\n        for (int i = 0; i < r; i++) {\n            x <<= 1;\n            boolean bit = readBoolean();\n            if (bit) x |= 1;\n        }\n        return x;\n    }\n\n\n   /**\n     * Reads the remaining bytes of data from this binary input stream and return as a string.\n     *\n     * @return the remaining bytes of data from this binary input stream as a {@code String}\n     * @throws NoSuchElementException if this binary input stream is empty or if the number of bits\n     *         available is not a multiple of 8 (byte-aligned)\n     */\n    public String readString() {\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n\n        StringBuilder sb = new StringBuilder();\n        while (!isEmpty()) {\n            char c = readChar();\n            sb.append(c);\n        }\n        return sb.toString();\n    }\n\n\n   /**\n     * Reads the next 16 bits from this binary input stream and return as a 16-bit short.\n     *\n     * @return the next 16 bits of data from this binary input stream as a {@code short}\n     * @throws NoSuchElementException if there are fewer than 16 bits available\n     */\n    public short readShort() {\n        short x = 0;\n        for (int i = 0; i < 2; i++) {\n            char c = readChar();\n            x <<= 8;\n            x |= c;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next 32 bits from this binary input stream and return as a 32-bit int.\n     *\n     * @return the next 32 bits of data from this binary input stream as a {@code int}\n     * @throws NoSuchElementException if there are fewer than 32 bits available\n     */\n    public int readInt() {\n        int x = 0;\n        for (int i = 0; i < 4; i++) {\n            char c = readChar();\n            x <<= 8;\n            x |= c;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next <em>r</em> bits from this binary input stream return\n     * as an <em>r</em>-bit int.\n     *\n     * @param  r number of bits to read\n     * @return the next {@code r} bits of data from this binary input stream as a {@code int}\n     * @throws NoSuchElementException if there are fewer than r bits available\n     * @throws IllegalArgumentException unless {@code 1 <= r <= 32}\n     */\n    public int readInt(int r) {\n        if (r < 1 || r > 32) throw new IllegalArgumentException(\"Illegal value of r = \" + r);\n\n        // optimize r = 32 case\n        if (r == 32) return readInt();\n\n        int x = 0;\n        for (int i = 0; i < r; i++) {\n            x <<= 1;\n            boolean bit = readBoolean();\n            if (bit) x |= 1;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next 64 bits from this binary input stream and return as a 64-bit long.\n     *\n     * @return the next 64 bits of data from this binary input stream as a {@code long}\n     * @throws NoSuchElementException if there are fewer than 64 bits available\n     */\n    public long readLong() {\n        long x = 0;\n        for (int i = 0; i < 8; i++) {\n            char c = readChar();\n            x <<= 8;\n            x |= c;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next 64 bits from this binary input stream and return as a 64-bit double.\n     *\n     * @return the next 64 bits of data from this binary input stream as a {@code double}\n     * @throws NoSuchElementException if there are fewer than 64 bits available\n     */\n    public double readDouble() {\n        return Double.longBitsToDouble(readLong());\n    }\n\n   /**\n     * Reads the next 32 bits from this binary input stream and return as a 32-bit float.\n     *\n     * @return the next 32 bits of data from this binary input stream as a {@code float}\n     * @throws NoSuchElementException if there are fewer than 32 bits available\n     */\n    public float readFloat() {\n        return Float.intBitsToFloat(readInt());\n    }\n\n\n   /**\n     * Reads the next 8 bits from this binary input stream and return as an 8-bit byte.\n     *\n     * @return the next 8 bits of data from this binary input stream as a {@code byte}\n     * @throws NoSuchElementException if there are fewer than 8 bits available\n     */\n    public byte readByte() {\n        char c = readChar();\n        return (byte) (c & 0xff);\n    }\n\n   /**\n     * Unit tests the {@code BinaryIn} data type.\n     * Reads the name of a file or URL (first command-line argument)\n     * and writes it to a file (second command-line argument).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        BinaryIn  in  = new BinaryIn(args[0]);\n        BinaryOut out = new BinaryOut(args[1]);\n\n        // read one 8-bit char at a time\n        while (!in.isEmpty()) {\n            char c = in.readChar();\n            out.write(c);\n        }\n        out.flush();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinaryInsertion.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinaryInsertion.java\n *  Execution:    java BinaryInsertion < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/21elementary/tiny.txt\n *                https://algs4.cs.princeton.edu/21elementary/words3.txt\n *\n *  Sorts a sequence of strings from standard input using\n *  binary insertion sort with half exchanges.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java BinaryInsertion < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java BinaryInsertion < words3.txt\n *  all bad bed bug dad ... yes yet zoo   [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BinaryInsertion} class provides a static method for sorting an\n *  array using an optimized binary insertion sort with half exchanges.\n *  <p>\n *  In the worst case, this implementation makes\n *  ~ <em>n</em> log<sub>2</sub><em>n</em> compares to sort an array of length\n *  <em>n</em>. However, in the worst case, the running time is\n *  &Theta;(<em>n</em><sup>2</sup>) because the number of array accesses\n *  can be quadratic.\n *  As such, it is not suitable for sorting large arrays\n *  (unless the number of inversions is small).\n *  <p>\n *  This sorting algorithm is stable.\n *  It uses &Theta;(1) extra memory (not including the input array).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/21elementary\">Section 2.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Ivan Pesin\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BinaryInsertion {\n\n    // This class should not be instantiated.\n    private BinaryInsertion() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        int n = a.length;\n        for (int i = 1; i < n; i++) {\n\n            // binary search to determine index j at which to insert a[i]\n            Comparable v = a[i];\n            int lo = 0, hi = i;\n            while (lo < hi) {\n                int mid = lo + (hi - lo) / 2;\n                if (less(v, a[mid])) hi = mid;\n                else                 lo = mid + 1;\n            }\n\n            // insertion sort with \"half exchanges\"\n            // (insert a[i] at index j and shift a[j], ..., a[i-1] to right)\n            for (int j = i; j > lo; --j)\n                a[j] = a[j-1];\n            a[lo] = v;\n        }\n        assert isSorted(a);\n    }\n\n\n\n   /***************************************************************************\n    *  Helper sorting function.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length - 1);\n    }\n\n    // is the array sorted from a[lo] to a[hi]\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo+1; i <= hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; insertion sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        BinaryInsertion.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinaryOut.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinaryOut.java\n *  Execution:    java BinaryOut\n *  Dependencies: none\n *\n *  Write binary data to an output stream, either one 1-bit boolean,\n *  one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,\n *  or one 64-bit long at a time. The output stream can be standard\n *  output, a file, an OutputStream or a Socket.\n *\n *  The bytes written are not aligned.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.BufferedOutputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.net.Socket;\n\n/**\n *  The <code>BinaryOut</code> data type provides a basic capability for\n *  converting primitive type variables ({@code boolean}, {@code byte},\n *  {@code char}, {@code int}, {@code long}, {@code float}, and {@code double})\n *  to sequences of bits and writing them to an output stream.\n *  The output stream can be standard output, a file, an OutputStream or a Socket.\n *  Uses big-endian (most-significant byte first).\n *  <p>\n *  The client must {@code flush()} the output stream when finished writing bits.\n *  <p>\n *  The client should not intermix calls to {@code BinaryOut} with calls\n *  to {@code Out}; otherwise unexpected behavior will result.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class BinaryOut {\n\n    private BufferedOutputStream out;  // the output stream\n    private int buffer;                // 8-bit buffer of bits to write out\n    private int n;                     // number of bits remaining in buffer\n\n\n   /**\n     * Initializes a binary output stream from standard output.\n     */\n    public BinaryOut() {\n        out = new BufferedOutputStream(System.out);\n    }\n\n   /**\n     * Initializes a binary output stream from an {@code OutputStream}.\n     * @param os the {@code OutputStream}\n     */\n    public BinaryOut(OutputStream os) {\n        out = new BufferedOutputStream(os);\n    }\n\n   /**\n     * Initializes a binary output stream from a file.\n     * @param  filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if cannot write the file {@code filename}\n     */\n    public BinaryOut(String filename) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename argument is null\");\n        }\n\n        if (filename.length() == 0) {\n            throw new IllegalArgumentException(\"filename argument is the empty string\");\n        }\n\n        try {\n            OutputStream os = new FileOutputStream(filename);\n            out = new BufferedOutputStream(os);\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not create file '\" + filename + \"' for writing\", e);\n        }\n    }\n\n   /**\n     * Initializes a binary output stream from a socket.\n     * @param socket the socket\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if cannot create output stream from socket\n     */\n    public BinaryOut(Socket socket) {\n        if (socket == null) {\n            throw new IllegalArgumentException(\"socket argument is null\");\n        }\n\n        try {\n            OutputStream os = socket.getOutputStream();\n            out = new BufferedOutputStream(os);\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not create output stream from socket\", e);\n        }\n    }\n\n\n   /**\n     * Writes the specified bit to the binary output stream.\n     * @param x the bit\n     */\n    private void writeBit(boolean x) {\n        // add bit to buffer\n        buffer <<= 1;\n        if (x) buffer |= 1;\n\n        // if buffer is full (8 bits), write out as a single byte\n        n++;\n        if (n == 8) clearBuffer();\n    }\n\n   /**\n     * Writes the 8-bit byte to the binary output stream.\n     * @param x the byte\n     */\n    private void writeByte(int x) {\n        assert x >= 0 && x < 256;\n\n        // optimized if byte-aligned\n        if (n == 0) {\n            try {\n                out.write(x);\n            }\n            catch (IOException e) {\n                e.printStackTrace();\n            }\n            return;\n        }\n\n        // otherwise write one bit at a time\n        for (int i = 0; i < 8; i++) {\n            boolean bit = ((x >>> (8 - i - 1)) & 1) == 1;\n            writeBit(bit);\n        }\n    }\n\n    // write out any remaining bits in buffer to the binary output stream, padding with 0s\n    private void clearBuffer() {\n        if (n == 0) return;\n        if (n > 0) buffer <<= (8 - n);\n        try {\n            out.write(buffer);\n        }\n        catch (IOException e) {\n            e.printStackTrace();\n        }\n        n = 0;\n        buffer = 0;\n    }\n\n   /**\n     * Flushes the binary output stream, padding 0s if number of bits written so far\n     * is not a multiple of 8.\n     */\n    public void flush() {\n        clearBuffer();\n        try {\n            out.flush();\n        }\n        catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n\n   /**\n     * Flushes and closes the binary output stream.\n     * Once it is closed, bits can no longer be written.\n     */\n    public void close() {\n        flush();\n        try {\n            out.close();\n        }\n        catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n\n\n   /**\n     * Writes the specified bit to the binary output stream.\n     * @param x the {@code boolean} to write\n     */\n    public void write(boolean x) {\n        writeBit(x);\n    }\n\n   /**\n     * Writes the 8-bit byte to the binary output stream.\n     * @param x the {@code byte} to write.\n     */\n    public void write(byte x) {\n        writeByte(x & 0xff);\n    }\n\n   /**\n     * Writes the 32-bit int to the binary output stream.\n     * @param x the {@code int} to write\n     */\n    public void write(int x) {\n        writeByte((x >>> 24) & 0xff);\n        writeByte((x >>> 16) & 0xff);\n        writeByte((x >>>  8) & 0xff);\n        writeByte((x >>>  0) & 0xff);\n    }\n\n   /**\n     * Writes the <em>r</em>-bit int to the binary output stream.\n     *\n     * @param  x the {@code int} to write\n     * @param  r the number of relevant bits in the char\n     * @throws IllegalArgumentException unless {@code r} is between 1 and 32\n     * @throws IllegalArgumentException unless {@code x} is between 0 and 2<sup>r</sup> - 1\n     */\n    public void write(int x, int r) {\n        if (r == 32) {\n            write(x);\n            return;\n        }\n        if (r < 1 || r > 32) throw new IllegalArgumentException(\"Illegal value for r = \" + r);\n        if (x >= (1 << r))   throw new IllegalArgumentException(\"Illegal \" + r + \"-bit char = \" + x);\n        for (int i = 0; i < r; i++) {\n            boolean bit = ((x >>> (r - i - 1)) & 1) == 1;\n            writeBit(bit);\n        }\n    }\n\n\n   /**\n     * Writes the 64-bit double to the binary output stream.\n     * @param x the {@code double} to write\n     */\n    public void write(double x) {\n        write(Double.doubleToRawLongBits(x));\n    }\n\n   /**\n     * Writes the 64-bit long to the binary output stream.\n     * @param x the {@code long} to write\n     */\n    public void write(long x) {\n        writeByte((int) ((x >>> 56) & 0xff));\n        writeByte((int) ((x >>> 48) & 0xff));\n        writeByte((int) ((x >>> 40) & 0xff));\n        writeByte((int) ((x >>> 32) & 0xff));\n        writeByte((int) ((x >>> 24) & 0xff));\n        writeByte((int) ((x >>> 16) & 0xff));\n        writeByte((int) ((x >>>  8) & 0xff));\n        writeByte((int) ((x >>>  0) & 0xff));\n    }\n\n   /**\n     * Writes the 32-bit float to the binary output stream.\n     * @param x the {@code float} to write\n     */\n    public void write(float x) {\n        write(Float.floatToRawIntBits(x));\n    }\n\n   /**\n     * Write the 16-bit int to the binary output stream.\n     * @param x the {@code short} to write.\n     */\n    public void write(short x) {\n        writeByte((x >>>  8) & 0xff);\n        writeByte((x >>>  0) & 0xff);\n    }\n\n   /**\n     * Writes the 8-bit char to the binary output stream.\n     *\n     * @param  x the {@code char} to write\n     * @throws IllegalArgumentException unless {@code x} is between 0 and 255\n     */\n    public void write(char x) {\n        if (x >= 256) throw new IllegalArgumentException(\"Illegal 8-bit char = \" + x);\n        writeByte(x);\n    }\n\n   /**\n     * Writes the <em>r</em>-bit char to the binary output stream.\n     *\n     * @param  x the {@code char} to write\n     * @param  r the number of relevant bits in the char\n     * @throws IllegalArgumentException unless {@code r} is between 1 and 16\n     * @throws IllegalArgumentException unless {@code x} is between 0 and 2<sup>r</sup> - 1\n     */\n    public void write(char x, int r) {\n        if (r == 8) {\n            write(x);\n            return;\n        }\n        if (r < 1 || r > 16) throw new IllegalArgumentException(\"Illegal value for r = \" + r);\n        if (x >= (1 << r))   throw new IllegalArgumentException(\"Illegal \" + r + \"-bit char = \" + x);\n        for (int i = 0; i < r; i++) {\n            boolean bit = ((x >>> (r - i - 1)) & 1) == 1;\n            writeBit(bit);\n        }\n    }\n\n   /**\n     * Writes the string of 8-bit characters to the binary output stream.\n     *\n     * @param  s the {@code String} to write\n     * @throws IllegalArgumentException if any character in the string is not\n     *         between 0 and 255\n     */\n    public void write(String s) {\n        for (int i = 0; i < s.length(); i++)\n            write(s.charAt(i));\n    }\n\n\n   /**\n     * Writes the string of <em>r</em>-bit characters to the binary output stream.\n     * @param  s the {@code String} to write\n     * @param  r the number of relevant bits in each character\n     * @throws IllegalArgumentException unless r is between 1 and 16\n     * @throws IllegalArgumentException if any character in the string is not\n     *         between 0 and 2<sup>r</sup> - 1\n     */\n    public void write(String s, int r) {\n        for (int i = 0; i < s.length(); i++)\n            write(s.charAt(i), r);\n    }\n\n\n   /**\n     * Test client. Read bits from standard input and write to the file\n     * specified on command line.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // create binary output stream to write to file\n        String filename = args[0];\n        BinaryOut out = new BinaryOut(filename);\n        BinaryIn  in  = new BinaryIn();\n\n        // read from standard input and write to file\n        while (!in.isEmpty()) {\n            char c = in.readChar();\n            out.write(c);\n        }\n        out.flush();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinarySearch.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinarySearch.java\n *  Execution:    java BinarySearch allowlist.txt < input.txt\n *  Dependencies: In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/11model/tinyAllowlist.txt\n *                https://algs4.cs.princeton.edu/11model/tinyText.txt\n *                https://algs4.cs.princeton.edu/11model/largeAllowlist.txt\n *                https://algs4.cs.princeton.edu/11model/largeText.txt\n *\n *  % java BinarySearch tinyAllowlist.txt < tinyText.txt\n *  50\n *  99\n *  13\n *\n *  % java BinarySearch largeAllowlist.txt < largeText.txt | more\n *  499569\n *  984875\n *  295754\n *  207807\n *  140925\n *  161828\n *  [367,966 total values]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n *  The {@code BinarySearch} class provides a static method for binary\n *  searching for an integer in a sorted array of integers.\n *  <p>\n *  The <em>indexOf</em> operations takes logarithmic time in the worst case.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/11model\">Section 1.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BinarySearch {\n\n    /**\n     * This class should not be instantiated.\n     */\n    private BinarySearch() { }\n\n    /**\n     * Returns the index of the specified key in the specified array.\n     *\n     * @param  a the array of integers, must be sorted in ascending order\n     * @param  key the search key\n     * @return index of key in array {@code a} if present; {@code -1} otherwise\n     */\n    public static int indexOf(int[] a, int key) {\n        int lo = 0;\n        int hi = a.length - 1;\n        while (lo <= hi) {\n            // Key is in a[lo..hi] or not present.\n            int mid = lo + (hi - lo) / 2;\n            if      (key < a[mid]) hi = mid - 1;\n            else if (key > a[mid]) lo = mid + 1;\n            else return mid;\n        }\n        return -1;\n    }\n\n    /**\n     * Returns the index of the specified key in the specified array.\n     * This function is poorly named because it does not give the <em>rank</em>\n     * if the array has duplicate keys or if the key is not in the array.\n     *\n     * @param  key the search key\n     * @param  a the array of integers, must be sorted in ascending order\n     * @return index of key in array {@code a} if present; {@code -1} otherwise\n     * @deprecated Replaced by {@link #indexOf(int[], int)}.\n     */\n    @Deprecated\n    public static int rank(int key, int[] a) {\n        return indexOf(a, key);\n    }\n\n    /**\n     * Reads in a sequence of integers from the allowlist file, specified as\n     * a command-line argument; reads in integers from standard input;\n     * prints to standard output those integers that do <em>not</em> appear in the file.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read the integers from a file\n        In in = new In(args[0]);\n        int[] allowlist = in.readAllInts();\n\n        // sort the array\n        Arrays.sort(allowlist);\n\n        // read integer key from standard input; print if not in allowlist\n        while (!StdIn.isEmpty()) {\n            int key = StdIn.readInt();\n            if (BinarySearch.indexOf(allowlist, key) == -1)\n                StdOut.println(key);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinarySearchST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinarySearchST.java\n *  Execution:    java BinarySearchST\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/31elementary/tinyST.txt\n *\n *  Symbol table implementation with binary search in an ordered array.\n *\n *  % more tinyST.txt\n *  S E A R C H E X A M P L E\n *\n *  % java BinarySearchST < tinyST.txt\n *  A 8\n *  C 4\n *  E 12\n *  H 5\n *  L 11\n *  M 9\n *  P 10\n *  R 3\n *  S 0\n *  X 7\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code BST} class represents an ordered symbol table of generic\n *  key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides ordered methods for finding the <em>minimum</em>,\n *  <em>maximum</em>, <em>floor</em>, <em>select</em>, and <em>ceiling</em>.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  It requires that\n *  the key type implements the {@code Comparable} interface and calls the\n *  {@code compareTo()} and method to compare two keys. It does not call either\n *  {@code equals()} or {@code hashCode()}.\n *  <p>\n *  This implementation uses a <em>sorted array</em>.\n *  The <em>put</em> and <em>remove</em> operations take &Theta;(<em>n</em>)\n *  time in the worst case.\n *  The <em>contains</em>, <em>ceiling</em>, <em>floor</em>,\n *  and <em>rank</em> operations take &Theta;(log <em>n</em>) time in the worst\n *  case.\n *  The <em>size</em>, <em>is-empty</em>, <em>minimum</em>, <em>maximum</em>,\n *  and <em>select</em> operations take &Theta;(1) time.\n *  Construction takes &Theta;(1) time.\n *  <p>\n *  For alternative implementations of the symbol table API,\n *  see {@link ST}, {@link BST}, {@link SequentialSearchST}, {@link RedBlackBST},\n *  {@link SeparateChainingHashST}, and {@link LinearProbingHashST},\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/31elementary\">Section 3.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class BinarySearchST<Key extends Comparable<Key>, Value> {\n    private static final int INIT_CAPACITY = 2;\n    private Key[] keys;\n    private Value[] vals;\n    private int n = 0;\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public BinarySearchST() {\n        this(INIT_CAPACITY);\n    }\n\n    /**\n     * Initializes an empty symbol table with the specified initial capacity.\n     * @param capacity the maximum capacity\n     */\n    public BinarySearchST(int capacity) {\n        keys = (Key[]) new Comparable[capacity];\n        vals = (Value[]) new Object[capacity];\n    }\n\n    // resize the underlying arrays\n    private void resize(int capacity) {\n        assert capacity >= n;\n        Key[]   tempk = (Key[])   new Comparable[capacity];\n        Value[] tempv = (Value[]) new Object[capacity];\n        for (int i = 0; i < n; i++) {\n            tempk[i] = keys[i];\n            tempv[i] = vals[i];\n        }\n        vals = tempv;\n        keys = tempk;\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     *\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     *\n     * @return {@code true} if this symbol table is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n\n    /**\n     * Does this symbol table contain the given key?\n     *\n     * @param  key the key\n     * @return {@code true} if this symbol table contains {@code key} and\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        return get(key) != null;\n    }\n\n    /**\n     * Returns the value associated with the given key in this symbol table.\n     *\n     * @param  key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *         and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        if (isEmpty()) return null;\n        int i = rank(key);\n        if (i < n && keys[i].compareTo(key) == 0) return vals[i];\n        return null;\n    }\n\n    /**\n     * Returns the number of keys in this symbol table strictly less than {@code key}.\n     *\n     * @param  key the key\n     * @return the number of keys in the symbol table strictly less than {@code key}\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public int rank(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to rank() is null\");\n\n        int lo = 0, hi = n-1;\n        while (lo <= hi) {\n            int mid = lo + (hi - lo) / 2;\n            int cmp = key.compareTo(keys[mid]);\n            if      (cmp < 0) hi = mid - 1;\n            else if (cmp > 0) lo = mid + 1;\n            else return mid;\n        }\n        return lo;\n    }\n\n\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val)  {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n\n        if (val == null) {\n            delete(key);\n            return;\n        }\n\n        int i = rank(key);\n\n        // key is already in table\n        if (i < n && keys[i].compareTo(key) == 0) {\n            vals[i] = val;\n            return;\n        }\n\n        // insert new key-value pair\n        if (n == keys.length) resize(2*keys.length);\n\n        for (int j = n; j > i; j--)  {\n            keys[j] = keys[j-1];\n            vals[j] = vals[j-1];\n        }\n        keys[i] = key;\n        vals[i] = val;\n        n++;\n\n        assert check();\n    }\n\n    /**\n     * Removes the specified key and associated value from this symbol table\n     * (if the key is in the symbol table).\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        if (isEmpty()) return;\n\n        // compute rank\n        int i = rank(key);\n\n        // key not in table\n        if (i == n || keys[i].compareTo(key) != 0) {\n            return;\n        }\n\n        for (int j = i; j < n-1; j++)  {\n            keys[j] = keys[j+1];\n            vals[j] = vals[j+1];\n        }\n\n        n--;\n        keys[n] = null;  // to avoid loitering\n        vals[n] = null;\n\n        // resize if 1/4 full\n        if (n > 0 && n == keys.length/4) resize(keys.length/2);\n\n        assert check();\n    }\n\n    /**\n     * Removes the smallest key and associated value from this symbol table.\n     *\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMin() {\n        if (isEmpty()) throw new NoSuchElementException(\"Symbol table underflow error\");\n        delete(min());\n    }\n\n    /**\n     * Removes the largest key and associated value from this symbol table.\n     *\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMax() {\n        if (isEmpty()) throw new NoSuchElementException(\"Symbol table underflow error\");\n        delete(max());\n    }\n\n\n   /***************************************************************************\n    *  Ordered symbol table methods.\n    ***************************************************************************/\n\n   /**\n     * Returns the smallest key in this symbol table.\n     *\n     * @return the smallest key in this symbol table\n     * @throws NoSuchElementException if this symbol table is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"called min() with empty symbol table\");\n        return keys[0];\n    }\n\n    /**\n     * Returns the largest key in this symbol table.\n     *\n     * @return the largest key in this symbol table\n     * @throws NoSuchElementException if this symbol table is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"called max() with empty symbol table\");\n        return keys[n-1];\n    }\n\n    /**\n     * Return the kth smallest key in this symbol table.\n     *\n     * @param  k the order statistic\n     * @return the {@code k}th smallest key in this symbol table\n     * @throws IllegalArgumentException unless {@code k} is between 0 and\n     *        <em>n</em>–1\n     */\n    public Key select(int k) {\n        if (k < 0 || k >= size()) {\n            throw new IllegalArgumentException(\"called select() with invalid argument: \" + k);\n        }\n        return keys[k];\n    }\n\n    /**\n     * Returns the largest key in this symbol table less than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the largest key in this symbol table less than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key floor(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to floor() is null\");\n        int i = rank(key);\n        if (i < n && key.compareTo(keys[i]) == 0) return keys[i];\n        if (i == 0) throw new NoSuchElementException(\"argument to floor() is too small\");\n        else return keys[i-1];\n    }\n\n    /**\n     * Returns the smallest key in this symbol table greater than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the smallest key in this symbol table greater than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key ceiling(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to ceiling() is null\");\n        int i = rank(key);\n        if (i == n) throw new NoSuchElementException(\"argument to ceiling() is too large\");\n        else return keys[i];\n    }\n\n    /**\n     * Returns the number of keys in this symbol table in the specified range.\n     *\n     * @param lo minimum endpoint\n     * @param hi maximum endpoint\n     * @return the number of keys in this symbol table between {@code lo}\n     *         (inclusive) and {@code hi} (inclusive)\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *         is {@code null}\n     */\n    public int size(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to size() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to size() is null\");\n\n        if (lo.compareTo(hi) > 0) return 0;\n        if (contains(hi)) return rank(hi) - rank(lo) + 1;\n        else              return rank(hi) - rank(lo);\n    }\n\n    /**\n     * Returns all keys in this symbol table as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     *\n     * @return all keys in this symbol table\n     */\n    public Iterable<Key> keys() {\n        return keys(min(), max());\n    }\n\n    /**\n     * Returns all keys in this symbol table in the given range,\n     * as an {@code Iterable}.\n     *\n     * @param lo minimum endpoint\n     * @param hi maximum endpoint\n     * @return all keys in this symbol table between {@code lo}\n     *         (inclusive) and {@code hi} (inclusive)\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *         is {@code null}\n     */\n    public Iterable<Key> keys(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to keys() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to keys() is null\");\n\n        Queue<Key> queue = new Queue<Key>();\n        if (lo.compareTo(hi) > 0) return queue;\n        for (int i = rank(lo); i < rank(hi); i++)\n            queue.enqueue(keys[i]);\n        if (contains(hi)) queue.enqueue(keys[rank(hi)]);\n        return queue;\n    }\n\n\n   /***************************************************************************\n    *  Check internal invariants.\n    ***************************************************************************/\n\n    private boolean check() {\n        return isSorted() && rankCheck();\n    }\n\n    // are the items in the array in ascending order?\n    private boolean isSorted() {\n        for (int i = 1; i < size(); i++)\n            if (keys[i].compareTo(keys[i-1]) < 0) return false;\n        return true;\n    }\n\n    // check that rank(select(i)) = i\n    private boolean rankCheck() {\n        for (int i = 0; i < size(); i++)\n            if (i != rank(select(i))) return false;\n        for (int i = 0; i < size(); i++)\n            if (keys[i].compareTo(select(rank(keys[i]))) != 0) return false;\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code BinarySearchST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        BinarySearchST<String, Integer> st = new BinarySearchST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinaryStdIn.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinaryStdIn.java\n *  Execution:    java BinaryStdIn < input > output\n *  Dependencies: none\n *\n *  Supports reading binary data from standard input.\n *\n *  % java BinaryStdIn < input.jpg > output.jpg\n *  % diff input.jpg output.jpg\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.BufferedInputStream;\nimport java.io.IOException;\nimport java.util.NoSuchElementException;\n\n/**\n *  The <code>BinaryStdIn</code> class provides static methods for reading\n *  in bits from standard input. It can process the bits\n *  one bit at a time (as a {@code boolean}),\n *  8 bits at a time (as a {@code byte} or {@code char}),\n *  16 bits at a time (as a {@code short}), 32 bits at a time\n *  (as an {@code int} or {@code float}), or 64 bits at a time (as a\n *  {@code double} or {@code long}).\n *  <p>\n *  All primitive types are assumed to be represented using their\n *  standard Java representations, in big-endian (most significant\n *  byte first) order.\n *  <p>\n *  The client should not intermix calls to {@code BinaryStdIn} with calls\n *  to {@code StdIn} or {@code System.in};\n *  otherwise unexpected behavior will result.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class BinaryStdIn {\n    private static final int EOF = -1;      // end of file\n\n    private static BufferedInputStream in;  // input stream\n    private static int buffer;              // one character buffer\n    private static int n;                   // number of bits left in buffer\n    private static boolean isInitialized;   // has BinaryStdIn been called for first time?\n\n    // don't instantiate\n    private BinaryStdIn() { }\n\n    // fill buffer\n    private static void initialize() {\n        in = new BufferedInputStream(System.in);\n        buffer = 0;\n        n = 0;\n        fillBuffer();\n        isInitialized = true;\n    }\n\n    private static void fillBuffer() {\n        try {\n            buffer = in.read();\n            n = 8;\n        }\n        catch (IOException e) {\n            System.out.println(\"EOF\");\n            buffer = EOF;\n            n = -1;\n        }\n    }\n\n   /**\n     * Close this input stream and release any associated system resources.\n     */\n    public static void close() {\n        if (!isInitialized) initialize();\n        try {\n            in.close();\n            isInitialized = false;\n        }\n        catch (IOException ioe) {\n            throw new IllegalStateException(\"Could not close BinaryStdIn\", ioe);\n        }\n    }\n\n   /**\n     * Returns true if standard input is empty.\n     * @return true if and only if standard input is empty\n     */\n    public static boolean isEmpty() {\n        if (!isInitialized) initialize();\n        return buffer == EOF;\n    }\n\n   /**\n     * Reads the next bit of data from standard input and return as a boolean.\n     *\n     * @return the next bit of data from standard input as a {@code boolean}\n     * @throws NoSuchElementException if standard input is empty\n     */\n    public static boolean readBoolean() {\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n        n--;\n        boolean bit = ((buffer >> n) & 1) == 1;\n        if (n == 0) fillBuffer();\n        return bit;\n    }\n\n   /**\n     * Reads the next 8 bits from standard input and return as an 8-bit char.\n     * Note that {@code char} is a 16-bit type;\n     * to read the next 16 bits as a char, use {@code readChar(16)}.\n     *\n     * @return the next 8 bits of data from standard input as a {@code char}\n     * @throws NoSuchElementException if there are fewer than 8 bits available on standard input\n     */\n    public static char readChar() {\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n\n        // special case when aligned byte\n        if (n == 8) {\n            int x = buffer;\n            fillBuffer();\n            return (char) (x & 0xff);\n        }\n\n        // combine last n bits of current buffer with first 8-n bits of new buffer\n        int x = buffer;\n        x <<= (8 - n);\n        int oldN = n;\n        fillBuffer();\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n        n = oldN;\n        x |= (buffer >>> n);\n        return (char) (x & 0xff);\n        // the above code doesn't quite work for the last character if n = 8\n        // because buffer will be -1, so there is a special case for aligned byte\n    }\n\n   /**\n     * Reads the next <em>r</em> bits from standard input and return as an <em>r</em>-bit character.\n     *\n     * @param  r number of bits to read.\n     * @return the next r bits of data from standard input as a {@code char}\n     * @throws NoSuchElementException if there are fewer than {@code r} bits available on standard input\n     * @throws IllegalArgumentException unless {@code 1 <= r <= 16}\n     */\n    public static char readChar(int r) {\n        if (r < 1 || r > 16) throw new IllegalArgumentException(\"Illegal value of r = \" + r);\n\n        // optimize r = 8 case\n        if (r == 8) return readChar();\n\n        char x = 0;\n        for (int i = 0; i < r; i++) {\n            x <<= 1;\n            boolean bit = readBoolean();\n            if (bit) x |= 1;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the remaining bytes of data from standard input and return as a string.\n     *\n     * @return the remaining bytes of data from standard input as a {@code String}\n     * @throws NoSuchElementException if standard input is empty or if the number of bits\n     *         available on standard input is not a multiple of 8 (byte-aligned)\n     */\n    public static String readString() {\n        if (isEmpty()) throw new NoSuchElementException(\"Reading from empty input stream\");\n\n        StringBuilder sb = new StringBuilder();\n        while (!isEmpty()) {\n            char c = readChar();\n            sb.append(c);\n        }\n        return sb.toString();\n    }\n\n\n   /**\n     * Reads the next 16 bits from standard input and return as a 16-bit short.\n     *\n     * @return the next 16 bits of data from standard input as a {@code short}\n     * @throws NoSuchElementException if there are fewer than 16 bits available on standard input\n     */\n    public static short readShort() {\n        short x = 0;\n        for (int i = 0; i < 2; i++) {\n            char c = readChar();\n            x <<= 8;\n            x |= c;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next 32 bits from standard input and return as a 32-bit int.\n     *\n     * @return the next 32 bits of data from standard input as a {@code int}\n     * @throws NoSuchElementException if there are fewer than 32 bits available on standard input\n     */\n    public static int readInt() {\n        int x = 0;\n        for (int i = 0; i < 4; i++) {\n            char c = readChar();\n            x <<= 8;\n            x |= c;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next <em>r</em> bits from standard input and return as an <em>r</em>-bit int.\n     *\n     * @param  r number of bits to read.\n     * @return the next r bits of data from standard input as a {@code int}\n     * @throws NoSuchElementException if there are fewer than {@code r} bits available on standard input\n     * @throws IllegalArgumentException unless {@code 1 <= r <= 32}\n     */\n    public static int readInt(int r) {\n        if (r < 1 || r > 32) throw new IllegalArgumentException(\"Illegal value of r = \" + r);\n\n        // optimize r = 32 case\n        if (r == 32) return readInt();\n\n        int x = 0;\n        for (int i = 0; i < r; i++) {\n            x <<= 1;\n            boolean bit = readBoolean();\n            if (bit) x |= 1;\n        }\n        return x;\n    }\n\n   /**\n     * Reads the next 64 bits from standard input and return as a 64-bit long.\n     *\n     * @return the next 64 bits of data from standard input as a {@code long}\n     * @throws NoSuchElementException if there are fewer than 64 bits available on standard input\n     */\n    public static long readLong() {\n        long x = 0;\n        for (int i = 0; i < 8; i++) {\n            char c = readChar();\n            x <<= 8;\n            x |= c;\n        }\n        return x;\n    }\n\n\n   /**\n     * Reads the next 64 bits from standard input and return as a 64-bit double.\n     *\n     * @return the next 64 bits of data from standard input as a {@code double}\n     * @throws NoSuchElementException if there are fewer than 64 bits available on standard input\n     */\n    public static double readDouble() {\n        return Double.longBitsToDouble(readLong());\n    }\n\n   /**\n     * Reads the next 32 bits from standard input and return as a 32-bit float.\n     *\n     * @return the next 32 bits of data from standard input as a {@code float}\n     * @throws NoSuchElementException if there are fewer than 32 bits available on standard input\n     */\n    public static float readFloat() {\n        return Float.intBitsToFloat(readInt());\n    }\n\n\n   /**\n     * Reads the next 8 bits from standard input and return as an 8-bit byte.\n     *\n     * @return the next 8 bits of data from standard input as a {@code byte}\n     * @throws NoSuchElementException if there are fewer than 8 bits available on standard input\n     */\n    public static byte readByte() {\n        char c = readChar();\n        return (byte) (c & 0xff);\n    }\n\n   /**\n     * Test client. Reads in a binary input file from standard input and writes\n     * it to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read one 8-bit char at a time\n        while (!BinaryStdIn.isEmpty()) {\n            char c = BinaryStdIn.readChar();\n            BinaryStdOut.write(c);\n        }\n        BinaryStdOut.flush();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinaryStdOut.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BinaryStdOut.java\n *  Execution:    java BinaryStdOut\n *  Dependencies: none\n *\n *  Write binary data to standard output, either one 1-bit boolean,\n *  one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,\n *  or one 64-bit long at a time.\n *\n *  The bytes written are not aligned.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.BufferedOutputStream;\nimport java.io.IOException;\n\n/**\n *  The <code>BinaryStdOut</code> class provides static methods for converting\n *  primitive type variables ({@code boolean}, {@code byte}, {@code char},\n *  {@code int}, {@code long}, {@code float}, and {@code double})\n *  to sequences of bits and writing them to standard output.\n *  Uses big-endian (most-significant byte first).\n *  <p>\n *  The client must {@code flush()} the output stream when finished writing bits.\n *  <p>\n *  The client should not intermix calls to {@code BinaryStdOut} with calls\n *  to {@code StdOut} or {@code System.out}; otherwise unexpected behavior\n *  will result.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class BinaryStdOut {\n    private static BufferedOutputStream out;  // output stream (standard output)\n    private static int buffer;                // 8-bit buffer of bits to write\n    private static int n;                     // number of bits remaining in buffer\n    private static boolean isInitialized;     // has BinaryStdOut been called for first time?\n\n    // don't instantiate\n    private BinaryStdOut() { }\n\n    // initialize BinaryStdOut\n    private static void initialize() {\n        out = new BufferedOutputStream(System.out);\n        buffer = 0;\n        n = 0;\n        isInitialized = true;\n    }\n\n   /**\n     * Writes the specified bit to standard output.\n     */\n    private static void writeBit(boolean bit) {\n        if (!isInitialized) initialize();\n\n        // add bit to buffer\n        buffer <<= 1;\n        if (bit) buffer |= 1;\n\n        // if buffer is full (8 bits), write out as a single byte\n        n++;\n        if (n == 8) clearBuffer();\n    }\n\n   /**\n     * Writes the 8-bit byte to standard output.\n     */\n    private static void writeByte(int x) {\n        if (!isInitialized) initialize();\n\n        assert x >= 0 && x < 256;\n\n        // optimized if byte-aligned\n        if (n == 0) {\n            try {\n                out.write(x);\n            }\n            catch (IOException e) {\n                e.printStackTrace();\n            }\n            return;\n        }\n\n        // otherwise write one bit at a time\n        for (int i = 0; i < 8; i++) {\n            boolean bit = ((x >>> (8 - i - 1)) & 1) == 1;\n            writeBit(bit);\n        }\n    }\n\n    // write out any remaining bits in buffer to standard output, padding with 0s\n    private static void clearBuffer() {\n        if (!isInitialized) initialize();\n\n        if (n == 0) return;\n        if (n > 0) buffer <<= (8 - n);\n        try {\n            out.write(buffer);\n        }\n        catch (IOException e) {\n            e.printStackTrace();\n        }\n        n = 0;\n        buffer = 0;\n    }\n\n   /**\n     * Flushes standard output, padding 0s if number of bits written so far\n     * is not a multiple of 8.\n     */\n    public static void flush() {\n        clearBuffer();\n        try {\n            out.flush();\n        }\n        catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n\n   /**\n     * Flushes and closes standard output. Once standard output is closed, you can no\n     * longer write bits to it.\n     */\n    public static void close() {\n        flush();\n        try {\n            out.close();\n            isInitialized = false;\n        }\n        catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n\n\n   /**\n     * Writes the specified bit to standard output.\n     * @param x the {@code boolean} to write.\n     */\n    public static void write(boolean x) {\n        writeBit(x);\n    }\n\n   /**\n     * Writes the 8-bit byte to standard output.\n     * @param x the {@code byte} to write.\n     */\n    public static void write(byte x) {\n        writeByte(x & 0xff);\n    }\n\n   /**\n     * Writes the 32-bit int to standard output.\n     * @param x the {@code int} to write.\n     */\n    public static void write(int x) {\n        writeByte((x >>> 24) & 0xff);\n        writeByte((x >>> 16) & 0xff);\n        writeByte((x >>>  8) & 0xff);\n        writeByte((x >>>  0) & 0xff);\n    }\n\n   /**\n     * Writes the <em>r</em>-bit int to standard output.\n     * @param x the {@code int} to write.\n     * @param r the number of relevant bits in the char.\n     * @throws IllegalArgumentException if {@code r} is not between 1 and 32.\n     * @throws IllegalArgumentException if {@code x} is not between 0 and 2<sup>r</sup> - 1.\n     */\n    public static void write(int x, int r) {\n        if (r == 32) {\n            write(x);\n            return;\n        }\n        if (r < 1 || r > 32)        throw new IllegalArgumentException(\"Illegal value for r = \" + r);\n        if (x < 0 || x >= (1 << r)) throw new IllegalArgumentException(\"Illegal \" + r + \"-bit char = \" + x);\n        for (int i = 0; i < r; i++) {\n            boolean bit = ((x >>> (r - i - 1)) & 1) == 1;\n            writeBit(bit);\n        }\n    }\n\n\n\n\n\n   /**\n     * Writes the 64-bit double to standard output.\n     * @param x the {@code double} to write.\n     */\n    public static void write(double x) {\n        write(Double.doubleToRawLongBits(x));\n    }\n\n   /**\n     * Writes the 64-bit long to standard output.\n     * @param x the {@code long} to write.\n     */\n    public static void write(long x) {\n        writeByte((int) ((x >>> 56) & 0xff));\n        writeByte((int) ((x >>> 48) & 0xff));\n        writeByte((int) ((x >>> 40) & 0xff));\n        writeByte((int) ((x >>> 32) & 0xff));\n        writeByte((int) ((x >>> 24) & 0xff));\n        writeByte((int) ((x >>> 16) & 0xff));\n        writeByte((int) ((x >>>  8) & 0xff));\n        writeByte((int) ((x >>>  0) & 0xff));\n    }\n\n   /**\n     * Writes the 32-bit float to standard output.\n     * @param x the {@code float} to write.\n     */\n    public static void write(float x) {\n        write(Float.floatToRawIntBits(x));\n    }\n\n   /**\n     * Writes the 16-bit int to standard output.\n     * @param x the {@code short} to write.\n     */\n    public static void write(short x) {\n        writeByte((x >>>  8) & 0xff);\n        writeByte((x >>>  0) & 0xff);\n    }\n\n   /**\n     * Writes the 8-bit char to standard output.\n     * @param x the {@code char} to write.\n     * @throws IllegalArgumentException if {@code x} is not between 0 and 255.\n     */\n    public static void write(char x) {\n        if (x < 0 || x >= 256) throw new IllegalArgumentException(\"Illegal 8-bit char = \" + x);\n        writeByte(x);\n    }\n\n   /**\n     * Writes the <em>r</em>-bit char to standard output.\n     * @param x the {@code char} to write.\n     * @param r the number of relevant bits in the char.\n     * @throws IllegalArgumentException if {@code r} is not between 1 and 16.\n     * @throws IllegalArgumentException if {@code x} is not between 0 and 2<sup>r</sup> - 1.\n     */\n    public static void write(char x, int r) {\n        if (r == 8) {\n            write(x);\n            return;\n        }\n        if (r < 1 || r > 16) throw new IllegalArgumentException(\"Illegal value for r = \" + r);\n        if (x >= (1 << r))   throw new IllegalArgumentException(\"Illegal \" + r + \"-bit char = \" + x);\n        for (int i = 0; i < r; i++) {\n            boolean bit = ((x >>> (r - i - 1)) & 1) == 1;\n            writeBit(bit);\n        }\n    }\n\n   /**\n     * Writes the string of 8-bit characters to standard output.\n     * @param s the {@code String} to write.\n     * @throws IllegalArgumentException if any character in the string is not\n     * between 0 and 255.\n     */\n    public static void write(String s) {\n        for (int i = 0; i < s.length(); i++)\n            write(s.charAt(i));\n    }\n\n   /**\n     * Writes the string of <em>r</em>-bit characters to standard output.\n     * @param s the {@code String} to write.\n     * @param r the number of relevant bits in each character.\n     * @throws IllegalArgumentException if r is not between 1 and 16.\n     * @throws IllegalArgumentException if any character in the string is not\n     * between 0 and 2<sup>r</sup> - 1.\n     */\n    public static void write(String s, int r) {\n        for (int i = 0; i < s.length(); i++)\n            write(s.charAt(i), r);\n    }\n\n   /**\n     * Tests the methods in this class.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int m = Integer.parseInt(args[0]);\n\n        // write n integers to binary standard output\n        for (int i = 0; i < m; i++) {\n            BinaryStdOut.write(i);\n        }\n        BinaryStdOut.flush();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BinomialMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation: javac BinomialMinPQ.java\n *  Execution:\n *  \n *  A binomial heap.\n *  \n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.Comparator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The BinomialMinPQ class represents a priority queue of generic keys.\n *  It supports the usual insert and delete-the-minimum operations, \n *  along with the merging of two heaps together.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  It is possible to build the priority queue using a Comparator.\n *  If not, the natural order relation between the keys will be used.\n *  \n *  This implementation uses a binomial heap.\n *  The insert, delete-the-minimum, union, min-key\n *  and size operations take logarithmic time.\n *  The is-empty and constructor operations take constant time.\n * \n *  @author Tristan Claverie\n */\npublic class BinomialMinPQ<Key> implements Iterable<Key> {\n\tprivate Node head;    \t\t\t\t//head of the list of roots\n\tprivate final Comparator<Key> comp;\t//Comparator over the keys\n\t\n\t//Represents a Node of a Binomial Tree\n\tprivate class Node {\n\t\tKey key;\t\t\t\t\t\t//Key contained by the Node\n\t\tint order;\t\t\t\t\t\t//The order of the Binomial Tree rooted by this Node\n\t\tNode child, sibling;\t\t\t//child and sibling of this Node\n\t}\n\t\n\t/**\n\t * Initializes an empty priority queue\n\t * Worst case is O(1)\n\t */\n\tpublic BinomialMinPQ() {\n\t\tcomp = new MyComparator();\n\t}\n\t\n\t/**\n\t * Initializes an empty priority queue using the given Comparator\n\t * Worst case is O(1)\n\t * @param C a comparator over the keys\n\t */\n\tpublic BinomialMinPQ(Comparator<Key> C) {\n\t\tcomp = C;\n\t}\n\t\n\t/**\n\t * Initializes a priority queue with given keys\n\t * Worst case is O(n*log(n))\n\t * @param a an array of keys\n\t */\n\tpublic BinomialMinPQ(Key[] a) {\n\t\tcomp = new MyComparator();\n\t\tfor (Key k : a) insert(k);\n\t}\n\t\n\t/**\n\t * Initializes a priority queue with given keys using the given Comparator\n\t * Worst case is O(n*log(n))\n\t * @param C a comparator over the keys\n\t * @param a an array of keys\n\t */\n\tpublic BinomialMinPQ(Comparator<Key> C, Key[] a) {\n\t\tcomp = C;\n\t\tfor (Key k : a) insert(k);\n\t}\n\n\t/**\n\t * Whether the priority queue is empty\n\t * Worst case is O(1)\n\t * @return true if the priority queue is empty, false if not\n\t */\n\tpublic boolean isEmpty() {\n\t\treturn head == null;\n\t}\n\n\t/**\n\t * Number of elements currently on the priority queue\n\t * Worst case is O(log(n))\n\t * @throws java.lang.ArithmeticException if there are more than 2^63-1 elements in the queue\n\t * @return the number of elements on the priority queue\n\t */\n\tpublic int size() {\n\t\tint result = 0, tmp;\n\t\tfor (Node node = head; node != null; node = node.sibling) {\n\t\t\tif (node.order > 30) { throw new ArithmeticException(\"The number of elements cannot be evaluated, but the priority queue is still valid.\"); }\n\t\t\ttmp = 1 << node.order;\n\t\t\tresult |= tmp;\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Puts a Key in the heap\n\t * Worst case is O(log(n))\n\t * @param key a Key\n\t */\n\tpublic void insert(Key key) {\n\t\tNode x = new Node();\n\t\tx.key = key;\n\t\tx.order = 0;\n\t\tBinomialMinPQ<Key> H = new BinomialMinPQ<Key>(); //The Comparator oh the H heap is not used\n\t\tH.head = x;\n\t\tthis.head = this.union(H).head;\n\t}\n\n\t/**\n\t * Get the minimum key currently in the queue\n\t * Worst case is O(log(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key currently in the priority queue\n\t */\n\tpublic Key minKey() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\tNode min = head;\n\t\tNode current = head;\n\t\twhile (current.sibling != null) {\n\t\t\tmin = (greater(min.key, current.sibling.key)) ? current : min;\n\t\t\tcurrent = current.sibling;\n\t\t}\n\t\treturn min.key;\n\t}\n\n\t/**\n\t * Deletes the minimum key\n\t * Worst case is O(log(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key\n\t */\n\tpublic Key delMin() {\n\t\tif(isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\tNode min = eraseMin();\n\t\tNode x = (min.child == null) ? min : min.child;\n\t\tif (min.child != null) {\n\t\t\tmin.child = null;\n\t\t\tNode prevx = null, nextx = x.sibling;\n\t\t\twhile (nextx != null) {\n\t\t\t\tx.sibling = prevx;\n\t\t\t\tprevx = x;\n\t\t\t\tx = nextx;nextx = nextx.sibling;\n\t\t\t}\n\t\t\tx.sibling = prevx;\n\t\t\tBinomialMinPQ<Key> H = new BinomialMinPQ<Key>();\n\t\t\tH.head = x;\n\t\t\thead = union(H).head;\n\t\t}\n\t\treturn min.key;\n\t}\n\t\n\t/**\n\t * Merges two Binomial heaps together\n\t * This operation is destructive\n\t * Worst case is O(log(n))\n\t * @param heap a Binomial Heap to be merged with the current heap\n\t * @throws java.lang.IllegalArgumentException if the heap in parameter is null\n\t * @return the union of two heaps\n\t */\n\tpublic BinomialMinPQ<Key> union(BinomialMinPQ<Key> heap) {\n\t\tif (heap == null) throw new IllegalArgumentException(\"Cannot merge a Binomial Heap with null\");\n\t\tthis.head = merge(new Node(), this.head, heap.head).sibling;\n\t\tNode x = this.head;\n\t\tNode prevx = null, nextx = x.sibling;\n\t\twhile (nextx != null) {\n\t\t\tif (x.order < nextx.order ||\n\t\t\t   (nextx.sibling != null && nextx.sibling.order == x.order)) {\n\t\t\t\tprevx = x; x = nextx;\n\t\t\t} else if (greater(nextx.key, x.key)) {\n\t\t\t\tx.sibling = nextx.sibling;\n\t\t\t\tlink(nextx, x);\n\t\t\t} else {\n\t\t\t\tif (prevx == null) { this.head = nextx; }\n\t\t\t\telse { prevx.sibling = nextx; }\n\t\t\t\tlink(x, nextx);\n\t\t\t\tx = nextx;\n\t\t\t}\n\t\t\tnextx = x.sibling;\n\t\t}\n\t\treturn this;\n\t}\n\t\n\t/*************************************************\n\t * General helper functions\n\t ************************************************/\n\t\n\t//Compares two keys\n\tprivate boolean greater(Key n, Key m) {\n\t\tif (n == null) return false;\n\t\tif (m == null) return true;\n\t\treturn comp.compare(n, m) > 0;\n\t}\n\t\n\t//Assuming root1 holds a greater key than root2, root2 becomes the new root\n\tprivate void link(Node root1, Node root2) {\n\t\troot1.sibling = root2.child;\n\t\troot2.child = root1;\n\t\troot2.order++;\n\t}\n\t\n\t//Deletes and return the node containing the minimum key\n\tprivate Node eraseMin() {\n\t\tNode min = head;\n\t\tNode previous = null;\n\t\tNode current = head;\n\t\twhile (current.sibling != null) {\n\t\t\tif (greater(min.key, current.sibling.key)) {\n\t\t\t\tprevious = current;\n\t\t\t\tmin = current.sibling;\n\t\t\t}\n\t\t\tcurrent = current.sibling;\n\t\t}\n\t\tprevious.sibling = min.sibling;\n\t\tif (min == head) head = min.sibling;\n\t\treturn min;\n\t}\n\t\n\t/**************************************************\n\t * Functions for inserting a key in the heap\n\t *************************************************/\n\t\n\t//Merges two root lists into one, there can be up to 2 Binomial Trees of same order\n        private Node merge(Node h, Node x, Node y) {\n            if (x == null && y == null) return h;\n            else if (x == null) h.sibling = merge(y, null, y.sibling);\n            else if (y == null) h.sibling = merge(x, x.sibling, null);\n            else if (x.order < y.order) h.sibling = merge(x, x.sibling, y);\n            else                        h.sibling = merge(y, x, y.sibling);\n            return h;\n\t}\n\t\n\t/******************************************************************\n\t * Iterator\n\t *****************************************************************/\n\t\n\t/**\n\t * Gets an Iterator over the keys in the priority queue in ascending order\n\t * The Iterator does not implement the remove() method\n\t * iterator() : Worst case is O(n)\n\t * next() : \tWorst case is O(log(n))\n\t * hasNext() : \tWorst case is O(1)\n\t * @return an Iterator over the keys in the priority queue in ascending order\n\t */\n\tpublic Iterator<Key> iterator() {\n\t\treturn new MyIterator();\n\t}\n\t\n\tprivate class MyIterator implements Iterator<Key> {\n\t\tBinomialMinPQ<Key> data;\n\t\t\n\t\t//Constructor clones recursively the elements in the queue\n\t\t//It takes linear time\n\t\tpublic MyIterator() {\n\t\t\tdata = new BinomialMinPQ<Key>(comp);\n\t\t\tdata.head = clone(head, null);\n\t\t}\n\t\t\n\t\tprivate Node clone(Node x, Node parent) {\n\t\t\tif (x == null) return null;\n\t\t\tNode node = new Node();\n\t\t\tnode.key = x.key;\n\t\t\tnode.sibling = clone(x.sibling, parent);\n\t\t\tnode.child = clone(x.child, node);\n\t\t\treturn node;\n\t\t}\n\t\t\n\t\tpublic boolean hasNext() {\n\t\t\treturn !data.isEmpty();\n\t\t}\n\t\t\n\t\tpublic Key next() {\n                        if (!hasNext()) throw new NoSuchElementException();\n\t\t\treturn data.delMin();\n\t\t}\n\t\t\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Comparator\n\t **************************/\n\t\n\t//default Comparator\n\tprivate class MyComparator implements Comparator<Key> {\n\t\t@Override\n\t\tpublic int compare(Key key1, Key key2) {\n\t\t\treturn ((Comparable<Key>) key1).compareTo(key2);\n\t\t}\n\t}\n\t\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Bipartite.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Bipartite.java\n *  Execution:    java  Bipartite V E F\n *  Dependencies: Graph.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *                https://algs4.cs.princeton.edu/41graph/largeG.txt\n *\n *  Given a graph, find either (i) a bipartition or (ii) an odd-length cycle.\n *  Runs in O(E + V) time.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code Bipartite} class represents a data type for\n *  determining whether an undirected graph is <em>bipartite</em> or whether\n *  it has an <em>odd-length cycle</em>.\n *  A graph is bipartite if and only if it has no odd-length cycle.\n *  The <em>isBipartite</em> operation determines whether the graph is\n *  bipartite. If so, the <em>color</em> operation determines a\n *  bipartition; if not, the <em>oddCycle</em> operation determines a\n *  cycle with an odd number of edges.\n *  <p>\n *  This implementation uses <em>depth-first search</em>.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in\n *  the worst case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  See {@link BipartiteX} for a nonrecursive version that uses breadth-first\n *  search.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Bipartite {\n    private boolean isBipartite;   // is the graph bipartite?\n    private boolean[] color;       // color[v] gives vertices on one side of bipartition\n    private boolean[] marked;      // marked[v] = true iff v has been visited in DFS\n    private int[] edgeTo;          // edgeTo[v] = last edge on path to v\n    private Stack<Integer> cycle;  // odd-length cycle\n\n    /**\n     * Determines whether an undirected graph is bipartite and finds either a\n     * bipartition or an odd-length cycle.\n     *\n     * @param  graph the graph\n     */\n    public Bipartite(Graph graph) {\n        isBipartite = true;\n        color  = new boolean[graph.V()];\n        marked = new boolean[graph.V()];\n        edgeTo = new int[graph.V()];\n\n        for (int v = 0; v < graph.V(); v++) {\n            if (!marked[v]) {\n                dfs(graph, v);\n            }\n        }\n        assert check(graph);\n    }\n\n    private void dfs(Graph graph, int v) {\n        marked[v] = true;\n        for (int w : graph.adj(v)) {\n\n            // short circuit if odd-length cycle found\n            if (cycle != null) return;\n\n            // found uncolored vertex, so recur\n            if (!marked[w]) {\n                edgeTo[w] = v;\n                color[w] = !color[v];\n                dfs(graph, w);\n            }\n\n            // if v-w create an odd-length cycle, find it\n            else if (color[w] == color[v]) {\n                isBipartite = false;\n                cycle = new Stack<Integer>();\n                cycle.push(w);  // don't need this unless you want to include start vertex twice\n                for (int x = v; x != w; x = edgeTo[x]) {\n                    cycle.push(x);\n                }\n                cycle.push(w);\n            }\n        }\n    }\n\n    /**\n     * Returns true if the graph is bipartite.\n     *\n     * @return {@code true} if the graph is bipartite; {@code false} otherwise\n     */\n    public boolean isBipartite() {\n        return isBipartite;\n    }\n\n    /**\n     * Returns the side of the bipartite that vertex {@code v} is on.\n     *\n     * @param  v the vertex\n     * @return the side of the bipartition that vertex {@code v} is on; two vertices\n     *         are in the same side of the bipartition if and only if they have the\n     *         same color\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws UnsupportedOperationException if this method is called when the graph\n     *         is not bipartite\n     */\n    public boolean color(int v) {\n        validateVertex(v);\n        if (!isBipartite)\n            throw new UnsupportedOperationException(\"graph is not bipartite\");\n        return color[v];\n    }\n\n    /**\n     * Returns an odd-length cycle if the graph is not bipartite, and\n     * {@code null} otherwise.\n     *\n     * @return an odd-length cycle if the graph is not bipartite\n     *         (and hence has an odd-length cycle), and {@code null}\n     *         otherwise\n     */\n    public Iterable<Integer> oddCycle() {\n        return cycle;\n    }\n\n    private boolean check(Graph graph) {\n        // graph is bipartite\n        if (isBipartite) {\n            for (int v = 0; v < graph.V(); v++) {\n                for (int w : graph.adj(v)) {\n                    if (color[v] == color[w]) {\n                        System.err.printf(\"edge %d-%d with %d and %d in same side of bipartition\\n\", v, w, v, w);\n                        return false;\n                    }\n                }\n            }\n        }\n\n        // graph has an odd-length cycle\n        else {\n            // verify cycle\n            int first = -1, last = -1;\n            for (int v : oddCycle()) {\n                if (first == -1) first = v;\n                last = v;\n            }\n            if (first != last) {\n                System.err.printf(\"cycle begins with %d and ends with %d\\n\", first, last);\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code Bipartite} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V1 = Integer.parseInt(args[0]);\n        int V2 = Integer.parseInt(args[1]);\n        int E  = Integer.parseInt(args[2]);\n        int F  = Integer.parseInt(args[3]);\n\n        // create random bipartite graph with V1 vertices on left side,\n        // V2 vertices on right side, and E edges; then add F random edges\n        Graph graph = GraphGenerator.bipartite(V1, V2, E);\n        for (int i = 0; i < F; i++) {\n            int v = StdRandom.uniformInt(V1 + V2);\n            int w = StdRandom.uniformInt(V1 + V2);\n            graph.addEdge(v, w);\n        }\n\n        StdOut.println(graph);\n\n\n        Bipartite b = new Bipartite(graph);\n        if (b.isBipartite()) {\n            StdOut.println(\"Graph is bipartite\");\n            for (int v = 0; v < graph.V(); v++) {\n                StdOut.println(v + \": \" + b.color(v));\n            }\n        }\n        else {\n            StdOut.print(\"Graph has an odd-length cycle: \");\n            for (int x : b.oddCycle()) {\n                StdOut.print(x + \" \");\n            }\n            StdOut.println();\n        }\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BipartiteMatching.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BipartiteMatching.java\n *  Execution:    java BipartiteMatching V1 V2 E\n *  Dependencies: BipartiteX.java\n *\n *  Find a maximum cardinality matching (and minimum cardinality vertex cover)\n *  in a bipartite graph using the alternating path algorithm.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BipartiteMatching} class represents a data type for computing a\n *  <em>maximum (cardinality) matching</em> and a\n *  <em>minimum (cardinality) vertex cover</em> in a bipartite graph.\n *  A <em>bipartite graph</em> in a graph whose vertices can be partitioned\n *  into two disjoint sets such that every edge has one endpoint in either set.\n *  A <em>matching</em> in a graph is a subset of its edges with no common\n *  vertices. A <em>maximum matching</em> is a matching with the maximum number\n *  of edges.\n *  A <em>perfect matching</em> is a matching which matches all vertices in the graph.\n *  A <em>vertex cover</em> in a graph is a subset of its vertices such that\n *  every edge is incident to at least one vertex. A <em>minimum vertex cover</em>\n *  is a vertex cover with the minimum number of vertices.\n *  By Konig's theorem, in any bipartite\n *  graph, the maximum number of edges in matching equals the minimum number\n *  of vertices in a vertex cover.\n *  The maximum matching problem in <em>nonbipartite</em> graphs is\n *  also important, but all known algorithms for this more general problem\n *  are substantially more complicated.\n *  <p>\n *  This implementation uses the <em>alternating-path algorithm</em>.\n *  It is equivalent to reducing to the maximum-flow problem and running\n *  the augmenting-path algorithm on the resulting flow network, but it\n *  does so with less overhead.\n *  The constructor takes <em>O</em>((<em>E</em> + <em>V</em>) <em>V</em>)\n *  time, where <em>E</em> is the number of edges and <em>V</em> is the\n *  number of vertices in the graph.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  See also {@link HopcroftKarp}, which solves the problem in\n *  <em>O</em>(<em>E</em> sqrt(<em>V</em>)) using the Hopcroft-Karp\n *  algorithm and\n *  <a href = \"https://algs4.cs.princeton.edu/65reductions/BipartiteMatchingToMaxflow.java.html\">BipartiteMatchingToMaxflow</a>,\n *  which solves the problem in <em>O</em>((<em>E</em> + <em>V</em>) <em>V</em>)\n *  time via a reduction to maxflow.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/65reductions\">Section 6.5</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BipartiteMatching {\n    private static final int UNMATCHED = -1;\n\n    private final int V;                 // number of vertices in the graph\n    private BipartiteX bipartition;      // the bipartition\n    private int cardinality;             // cardinality of current matching\n    private int[] mate;                  // mate[v] =  w if v-w is an edge in current matching\n                                         //         = -1 if v is not in current matching\n    private boolean[] inMinVertexCover;  // inMinVertexCover[v] = true iff v is in min vertex cover\n    private boolean[] marked;            // marked[v] = true iff v is reachable via alternating path\n    private int[] edgeTo;                // edgeTo[v] = last edge on alternating path to v\n\n    /**\n     * Determines a maximum matching (and a minimum vertex cover)\n     * in a bipartite graph.\n     *\n     * @param  G the bipartite graph\n     * @throws IllegalArgumentException if {@code G} is not bipartite\n     */\n    public BipartiteMatching(Graph G) {\n        bipartition = new BipartiteX(G);\n        if (!bipartition.isBipartite()) {\n            throw new IllegalArgumentException(\"graph is not bipartite\");\n        }\n\n        this.V = G.V();\n\n        // initialize empty matching\n        mate = new int[V];\n        for (int v = 0; v < V; v++)\n            mate[v] = UNMATCHED;\n\n        // alternating path algorithm\n        while (hasAugmentingPath(G)) {\n\n            // find one endpoint t in alternating path\n            int t = -1;\n            for (int v = 0; v < G.V(); v++) {\n                if (!isMatched(v) && edgeTo[v] != -1) {\n                    t = v;\n                    break;\n                }\n            }\n\n            // update the matching according to alternating path in edgeTo[] array\n            for (int v = t; v != -1; v = edgeTo[edgeTo[v]]) {\n                int w = edgeTo[v];\n                mate[v] = w;\n                mate[w] = v;\n            }\n            cardinality++;\n        }\n\n        // find min vertex cover from marked[] array\n        inMinVertexCover = new boolean[V];\n        for (int v = 0; v < V; v++) {\n            if (bipartition.color(v) && !marked[v]) inMinVertexCover[v] = true;\n            if (!bipartition.color(v) && marked[v]) inMinVertexCover[v] = true;\n        }\n\n        assert certifySolution(G);\n    }\n\n\n    /*\n     * is there an augmenting path?\n     *   - if so, upon termination adj[] contains the level graph;\n     *   - if not, upon termination marked[] specifies those vertices reachable via an alternating\n     *     path from one side of the bipartition\n     *\n     * an alternating path is a path whose edges belong alternately to the matching and not\n     * to the matching\n     *\n     * an augmenting path is an alternating path that starts and ends at unmatched vertices\n     *\n     * this implementation finds a shortest augmenting path (fewest number of edges), though there\n     * is no particular advantage to do so here\n     */\n    private boolean hasAugmentingPath(Graph G) {\n        marked = new boolean[V];\n\n        edgeTo = new int[V];\n        for (int v = 0; v < V; v++)\n            edgeTo[v] = -1;\n\n        // breadth-first search (starting from all unmatched vertices on one side of bipartition)\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int v = 0; v < V; v++) {\n            if (bipartition.color(v) && !isMatched(v)) {\n                queue.enqueue(v);\n                marked[v] = true;\n            }\n        }\n\n        // run BFS, stopping as soon as an alternating path is found\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : G.adj(v)) {\n\n                // either (1) forward edge not in matching or (2) backward edge in matching\n                if (isResidualGraphEdge(v, w) && !marked[w]) {\n                    edgeTo[w] = v;\n                    marked[w] = true;\n                    if (!isMatched(w)) return true;\n                    queue.enqueue(w);\n                }\n            }\n        }\n\n        return false;\n    }\n\n    // is the edge v-w a forward edge not in the matching or a reverse edge in the matching?\n    private boolean isResidualGraphEdge(int v, int w) {\n        if ((mate[v] != w) &&  bipartition.color(v)) return true;\n        if ((mate[v] == w) && !bipartition.color(v)) return true;\n        return false;\n    }\n\n    /**\n     * Returns the vertex to which the specified vertex is matched in\n     * the maximum matching computed by the algorithm.\n     *\n     * @param  v the vertex\n     * @return the vertex to which vertex {@code v} is matched in the\n     *         maximum matching; {@code -1} if the vertex is not matched\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     *\n     */\n    public int mate(int v) {\n        validate(v);\n        return mate[v];\n    }\n\n    /**\n     * Returns true if the specified vertex is matched in the maximum matching\n     * computed by the algorithm.\n     *\n     * @param  v the vertex\n     * @return {@code true} if vertex {@code v} is matched in maximum matching;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     *\n     */\n    public boolean isMatched(int v) {\n        validate(v);\n        return mate[v] != UNMATCHED;\n    }\n\n    /**\n     * Returns the number of edges in a maximum matching.\n     *\n     * @return the number of edges in a maximum matching\n     */\n    public int size() {\n        return cardinality;\n    }\n\n    /**\n     * Returns true if the graph contains a perfect matching.\n     * That is, the number of edges in a maximum matching is equal to one half\n     * of the number of vertices in the graph (so that every vertex is matched).\n     *\n     * @return {@code true} if the graph contains a perfect matching;\n     *         {@code false} otherwise\n     */\n    public boolean isPerfect() {\n        return cardinality * 2 == V;\n    }\n\n    /**\n     * Returns true if the specified vertex is in the minimum vertex cover\n     * computed by the algorithm.\n     *\n     * @param  v the vertex\n     * @return {@code true} if vertex {@code v} is in the minimum vertex cover;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean inMinVertexCover(int v) {\n        validate(v);\n        return inMinVertexCover[v];\n    }\n\n    private void validate(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // check that mate[] and inVertexCover[] define a max matching and min vertex cover, respectively\n    private boolean certifySolution(Graph G) {\n\n        // check that mate(v) = w iff mate(w) = v\n        for (int v = 0; v < V; v++) {\n            if (mate(v) == -1) continue;\n            if (mate(mate(v)) != v) return false;\n        }\n\n        // check that size() is consistent with mate()\n        int matchedVertices = 0;\n        for (int v = 0; v < V; v++) {\n            if (mate(v) != -1) matchedVertices++;\n        }\n        if (2*size() != matchedVertices) return false;\n\n        // check that size() is consistent with minVertexCover()\n        int sizeOfMinVertexCover = 0;\n        for (int v = 0; v < V; v++)\n            if (inMinVertexCover(v)) sizeOfMinVertexCover++;\n        if (size() != sizeOfMinVertexCover) return false;\n\n        // check that mate() uses each vertex at most once\n        boolean[] isMatched = new boolean[V];\n        for (int v = 0; v < V; v++) {\n            int w = mate[v];\n            if (w == -1) continue;\n            if (v == w) return false;\n            if (v >= w) continue;\n            if (isMatched[v] || isMatched[w]) return false;\n            isMatched[v] = true;\n            isMatched[w] = true;\n        }\n\n        // check that mate() uses only edges that appear in the graph\n        for (int v = 0; v < V; v++) {\n            if (mate(v) == -1) continue;\n            boolean isEdge = false;\n            for (int w : G.adj(v)) {\n                if (mate(v) == w) isEdge = true;\n            }\n            if (!isEdge) return false;\n        }\n\n        // check that inMinVertexCover() is a vertex cover\n        for (int v = 0; v < V; v++)\n            for (int w : G.adj(v))\n                if (!inMinVertexCover(v) && !inMinVertexCover(w)) return false;\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code HopcroftKarp} data type.\n     * Takes three command-line arguments {@code V1}, {@code V2}, and {@code E};\n     * creates a random bipartite graph with {@code V1} + {@code V2} vertices\n     * and {@code E} edges; computes a maximum matching and minimum vertex cover;\n     * and prints the results.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V1 = Integer.parseInt(args[0]);\n        int V2 = Integer.parseInt(args[1]);\n        int E  = Integer.parseInt(args[2]);\n        Graph G = GraphGenerator.bipartite(V1, V2, E);\n\n        if (G.V() < 1000) StdOut.println(G);\n\n        BipartiteMatching matching = new BipartiteMatching(G);\n\n        // print maximum matching\n        StdOut.printf(\"Number of edges in max matching        = %d\\n\", matching.size());\n        StdOut.printf(\"Number of vertices in min vertex cover = %d\\n\", matching.size());\n        StdOut.printf(\"Graph has a perfect matching           = %b\\n\", matching.isPerfect());\n        StdOut.println();\n\n        if (G.V() >= 1000) return;\n\n        StdOut.print(\"Max matching: \");\n        for (int v = 0; v < G.V(); v++) {\n            int w = matching.mate(v);\n            if (matching.isMatched(v) && v < w)  // print each edge only once\n                StdOut.print(v + \"-\" + w + \" \");\n        }\n        StdOut.println();\n\n        // print minimum vertex cover\n        StdOut.print(\"Min vertex cover: \");\n        for (int v = 0; v < G.V(); v++)\n            if (matching.inMinVertexCover(v))\n                StdOut.print(v + \" \");\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BipartiteX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BipartiteX.java\n *  Execution:    java  Bipartite V E F\n *  Dependencies: Graph.java\n *\n *  Given a graph, find either (i) a bipartition or (ii) an odd-length cycle.\n *  Runs in O(E + V) time.\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code BipartiteX} class represents a data type for\n *  determining whether an undirected graph is <em>bipartite</em> or whether\n *  it has an <em>odd-length cycle</em>.\n *  A graph is bipartite if and only if it has no odd-length cycle.\n *  The <em>isBipartite</em> operation determines whether the graph is\n *  bipartite. If so, the <em>color</em> operation determines a\n *  bipartition; if not, the <em>oddCycle</em> operation determines a\n *  cycle with an odd number of edges.\n *  <p>\n *  This implementation uses <em>breadth-first search</em> and is nonrecursive.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in\n *  in the worst case, where <em>V</em> is the number of vertices\n *  and <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  See {@link Bipartite} for a recursive version that uses depth-first search.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BipartiteX {\n    private static final boolean WHITE = false;\n    private static final boolean BLACK = true;\n\n    private boolean isBipartite;   // is the graph bipartite?\n    private boolean[] color;       // color[v] gives vertices on one side of bipartition\n    private boolean[] marked;      // marked[v] = true iff v has been visited in DFS\n    private int[] edgeTo;          // edgeTo[v] = last edge on path to v\n    private Queue<Integer> cycle;  // odd-length cycle\n\n    /**\n     * Determines whether an undirected graph is bipartite and finds either a\n     * bipartition or an odd-length cycle.\n     *\n     * @param graph the graph\n     */\n    public BipartiteX(Graph graph) {\n        isBipartite = true;\n        color  = new boolean[graph.V()];\n        marked = new boolean[graph.V()];\n        edgeTo = new int[graph.V()];\n\n        for (int v = 0; v < graph.V() && isBipartite; v++) {\n            if (!marked[v]) {\n                bfs(graph, v);\n            }\n        }\n        assert check(graph);\n    }\n\n    private void bfs(Graph graph, int s) {\n        Queue<Integer> queue = new Queue<Integer>();\n        color[s] = WHITE;\n        marked[s] = true;\n        queue.enqueue(s);\n\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : graph.adj(v)) {\n                if (!marked[w]) {\n                    marked[w] = true;\n                    edgeTo[w] = v;\n                    color[w] = !color[v];\n                    queue.enqueue(w);\n                }\n                else if (color[w] == color[v]) {\n                    isBipartite = false;\n\n                    // to form odd cycle, consider s-v path and s-w path\n                    // and let x be closest node to v and w common to two paths\n                    // then (w-x path) + (x-v path) + (edge v-w) is an odd-length cycle\n                    // Note: distTo[v] == distTo[w];\n                    cycle = new Queue<Integer>();\n                    Stack<Integer> stack = new Stack<Integer>();\n                    int x = v, y = w;\n                    while (x != y) {\n                        stack.push(x);\n                        cycle.enqueue(y);\n                        x = edgeTo[x];\n                        y = edgeTo[y];\n                    }\n                    stack.push(x);\n                    while (!stack.isEmpty())\n                        cycle.enqueue(stack.pop());\n                    cycle.enqueue(w);\n                    return;\n                }\n            }\n        }\n    }\n\n    /**\n     * Returns true if the graph is bipartite.\n     *\n     * @return {@code true} if the graph is bipartite; {@code false} otherwise\n     */\n    public boolean isBipartite() {\n        return isBipartite;\n    }\n\n    /**\n     * Returns the side of the bipartite that vertex {@code v} is on.\n     *\n     * @param  v the vertex\n     * @return the side of the bipartition that vertex {@code v} is on; two vertices\n     *         are in the same side of the bipartition if and only if they have the\n     *         same color\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws UnsupportedOperationException if this method is called when the graph\n     *         is not bipartite\n     */\n    public boolean color(int v) {\n        validateVertex(v);\n        if (!isBipartite)\n            throw new UnsupportedOperationException(\"Graph is not bipartite\");\n        return color[v];\n    }\n\n\n    /**\n     * Returns an odd-length cycle if the graph is not bipartite, and\n     * {@code null} otherwise.\n     *\n     * @return an odd-length cycle if the graph is not bipartite\n     *         (and hence has an odd-length cycle), and {@code null}\n     *         otherwise\n     */\n    public Iterable<Integer> oddCycle() {\n        return cycle;\n    }\n\n    private boolean check(Graph graph) {\n        // graph is bipartite\n        if (isBipartite) {\n            for (int v = 0; v < graph.V(); v++) {\n                for (int w : graph.adj(v)) {\n                    if (color[v] == color[w]) {\n                        System.err.printf(\"edge %d-%d with %d and %d in same side of bipartition\\n\", v, w, v, w);\n                        return false;\n                    }\n                }\n            }\n        }\n\n        // graph has an odd-length cycle\n        else {\n            // verify cycle\n            int first = -1, last = -1;\n            for (int v : oddCycle()) {\n                if (first == -1) first = v;\n                last = v;\n            }\n            if (first != last) {\n                System.err.printf(\"cycle begins with %d and ends with %d\\n\", first, last);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code BipartiteX} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V1 = Integer.parseInt(args[0]);\n        int V2 = Integer.parseInt(args[1]);\n        int E  = Integer.parseInt(args[2]);\n        int F  = Integer.parseInt(args[3]);\n\n        // create random bipartite graph with V1 vertices on left side,\n        // V2 vertices on right side, and E edges; then add F random edges\n        Graph graph = GraphGenerator.bipartite(V1, V2, E);\n        for (int i = 0; i < F; i++) {\n            int v = StdRandom.uniformInt(V1 + V2);\n            int w = StdRandom.uniformInt(V1 + V2);\n            graph.addEdge(v, w);\n        }\n\n        StdOut.println(graph);\n\n\n        BipartiteX b = new BipartiteX(graph);\n        if (b.isBipartite()) {\n            StdOut.println(\"Graph is bipartite\");\n            for (int v = 0; v < graph.V(); v++) {\n                StdOut.println(v + \": \" + b.color(v));\n            }\n        }\n        else {\n            StdOut.print(\"Graph has an odd-length cycle: \");\n            for (int x : b.oddCycle()) {\n                StdOut.print(x + \" \");\n            }\n            StdOut.println();\n        }\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BlockFilter.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BlockFilter.java\n *  Execution:    java BlockFilter blocklist.txt < input.txt\n *  Dependencies: SET In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/tinyTale.txt\n *                https://algs4.cs.princeton.edu/35applications/blocklist.txt\n *\n *  Reads a blocklist of words from a file. Then reads a list of\n *  words from standard input and print all those words that\n *  are not in the first file.\n *\n *  % more tinyTale.txt\n *  it was the best of times it was the worst of times\n *  it was the age of wisdom it was the age of foolishness\n *  it was the epoch of belief it was the epoch of incredulity\n *  it was the season of light it was the season of darkness\n *  it was the spring of hope it was the winter of despair\n *\n *  % more list.txt\n *  was it the of\n *\n *  % java BlockFilter list.txt < tinyTale.txt\n *  best times worst times\n *  age wisdom age foolishness\n *  epoch belief epoch incredulity\n *  season light season darkness\n *  spring hope winter despair\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BlockFilter} class provides a client for reading in a <em>blocklist</em>\n *  of words from a file; then, reading in a sequence of words from standard input,\n *  printing out each word that <em>does not</em> appear in the file.\n *  It is useful as a test client for various symbol-table implementations.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BlockFilter {\n\n    // Do not instantiate.\n    private BlockFilter() { }\n\n    public static void main(String[] args) {\n        SET<String> set = new SET<String>();\n\n        // read in strings and add to set\n        In in = new In(args[0]);\n        while (!in.isEmpty()) {\n            String word = in.readString();\n            set.add(word);\n        }\n\n        // read in string from standard input, printing out all exceptions\n        while (!StdIn.isEmpty()) {\n            String word = StdIn.readString();\n            if (!set.contains(word))\n                StdOut.println(word);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BoruvkaMST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BoruvkaMST.java\n *  Execution:    java BoruvkaMST filename.txt\n *  Dependencies: EdgeWeightedGraph.java Edge.java Bag.java\n *                UF.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt\n *\n *  Compute a minimum spanning forest using Boruvka's algorithm.\n *\n *  % java BoruvkaMST tinyEWG.txt\n *  0-2 0.26000\n *  6-2 0.40000\n *  5-7 0.28000\n *  4-5 0.35000\n *  2-3 0.17000\n *  1-7 0.19000\n *  0-7 0.16000\n *  1.81000\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BoruvkaMST} class represents a data type for computing a\n *  <em>minimum spanning tree</em> in an edge-weighted graph.\n *  The edge weights can be positive, zero, or negative and need not\n *  be distinct. If the graph is not connected, it computes a <em>minimum\n *  spanning forest</em>, which is the union of minimum spanning trees\n *  in each connected component. The {@code weight()} method returns the\n *  weight of a minimum spanning tree and the {@code edges()} method\n *  returns its edges.\n *  <p>\n *  This implementation uses <em>Boruvka's algorithm</em> and the union-find\n *  data type.\n *  The constructor takes &Theta;(<em>E</em> log <em>V</em>) time in\n *  the worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted graph).\n *  <p>\n *  This {@code weight()} method correctly computes the weight of the MST\n *  if all arithmetic performed is without floating-point rounding error\n *  or arithmetic overflow.\n *  This is the case if all edge weights are non-negative integers\n *  and the weight of the MST does not exceed 2<sup>52</sup>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/43mst\">Section 4.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For alternate implementations, see {@link LazyPrimMST}, {@link PrimMST},\n *  and {@link KruskalMST}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BoruvkaMST {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-12;\n\n    private Bag<Edge> mst = new Bag<Edge>();    // edges in MST\n    private double weight;                      // weight of MST\n\n    /**\n     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.\n     * @param graph the edge-weighted graph\n     */\n    public BoruvkaMST(EdgeWeightedGraph graph) {\n        UF uf = new UF(graph.V());\n\n        // repeat at most log V times or until we have V-1 edges\n        for (int t = 1; t < graph.V() && mst.size() < graph.V() - 1; t = t + t) {\n\n            // foreach tree in forest, find closest edge\n            // if edge weights are equal, ties are broken in favor of first edge in graph.edges()\n            Edge[] closest = new Edge[graph.V()];\n            for (Edge e : graph.edges()) {\n                int v = e.either(), w = e.other(v);\n                int i = uf.find(v), j = uf.find(w);\n                if (i == j) continue;   // same tree\n                if (closest[i] == null || less(e, closest[i])) closest[i] = e;\n                if (closest[j] == null || less(e, closest[j])) closest[j] = e;\n            }\n\n            // add newly discovered edges to MST\n            for (int i = 0; i < graph.V(); i++) {\n                Edge e = closest[i];\n                if (e != null) {\n                    int v = e.either(), w = e.other(v);\n                    // don't add the same edge twice\n                    if (uf.find(v) != uf.find(w)) {\n                        mst.add(e);\n                        weight += e.weight();\n                        uf.union(v, w);\n                    }\n                }\n            }\n        }\n\n        // check optimality conditions\n        assert check(graph);\n    }\n\n    /**\n     * Returns the edges in a minimum spanning tree (or forest).\n     * @return the edges in a minimum spanning tree (or forest) as\n     *    an iterable of edges\n     */\n    public Iterable<Edge> edges() {\n        return mst;\n    }\n\n\n    /**\n     * Returns the sum of the edge weights in a minimum spanning tree (or forest).\n     * @return the sum of the edge weights in a minimum spanning tree (or forest)\n     */\n    public double weight() {\n        return weight;\n    }\n\n    // is the weight of edge e strictly less than that of edge f?\n    private static boolean less(Edge e, Edge f) {\n        return e.compareTo(f) < 0;\n    }\n\n    // check optimality conditions (takes time proportional to E V lg* V)\n    private boolean check(EdgeWeightedGraph graph) {\n\n        // check weight\n        double totalWeight = 0.0;\n        for (Edge e : edges()) {\n            totalWeight += e.weight();\n        }\n        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {\n            System.err.printf(\"Weight of edges does not equal weight(): %f vs. %f\\n\", totalWeight, weight());\n            return false;\n        }\n\n        // check that it is acyclic\n        UF uf = new UF(graph.V());\n        for (Edge e : edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) == uf.find(w)) {\n                System.err.println(\"Not a forest\");\n                return false;\n            }\n            uf.union(v, w);\n        }\n\n        // check that it is a spanning forest\n        for (Edge e : graph.edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) != uf.find(w)) {\n                System.err.println(\"Not a spanning forest\");\n                return false;\n            }\n        }\n\n        // check that it is a minimal spanning forest (cut optimality conditions)\n        for (Edge e : edges()) {\n\n            // all edges in MST except e\n            uf = new UF(graph.V());\n            for (Edge f : mst) {\n                int x = f.either(), y = f.other(x);\n                if (f != e) uf.union(x, y);\n            }\n\n            // check that e is min weight edge in crossing cut\n            for (Edge f : graph.edges()) {\n                int x = f.either(), y = f.other(x);\n                if (uf.find(x) != uf.find(y)) {\n                    if (f.weight() < e.weight()) {\n                        System.err.println(\"Edge \" + f + \" violates cut optimality conditions\");\n                        return false;\n                    }\n                }\n            }\n\n        }\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code BoruvkaMST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph graph = new EdgeWeightedGraph(in);\n        BoruvkaMST mst = new BoruvkaMST(graph);\n        for (Edge e : mst.edges()) {\n            StdOut.println(e);\n        }\n        StdOut.printf(\"%.5f\\n\", mst.weight());\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BoyerMoore.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BoyerMoore.java\n *  Execution:    java BoyerMoore pattern text\n *  Dependencies: StdOut.java\n *\n *  Reads in two strings, the pattern and the input text, and\n *  searches for the pattern in the input text using the\n *  bad-character rule part of the Boyer-Moore algorithm.\n *  (does not implement the strong good suffix rule)\n *\n *  % java BoyerMoore abracadabra abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:               abracadabra\n *\n *  % java BoyerMoore rab abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:         rab\n *\n *  % java BoyerMoore bcara abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:                                   bcara\n *\n *  % java BoyerMoore rabrabracad abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:                        rabrabracad\n *\n *  % java BoyerMoore abacad abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern: abacad\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BoyerMoore} class finds the first occurrence of a pattern string\n *  in a text string.\n *  <p>\n *  This implementation uses the Boyer-Moore algorithm (with the bad-character\n *  rule, but not the strong good suffix rule).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/53substring\">Section 5.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class BoyerMoore {\n    private final int R;     // the radix\n    private int[] right;     // the bad-character skip array\n\n    private char[] pattern;  // store the pattern as a character array\n    private String pat;      // or as a string\n\n    /**\n     * Preprocesses the pattern string.\n     *\n     * @param pat the pattern string\n     */\n    public BoyerMoore(String pat) {\n        this.R = 256;\n        this.pat = pat;\n\n        // position of rightmost occurrence of c in the pattern\n        right = new int[R];\n        for (int c = 0; c < R; c++)\n            right[c] = -1;\n        for (int j = 0; j < pat.length(); j++)\n            right[pat.charAt(j)] = j;\n    }\n\n    /**\n     * Preprocesses the pattern string.\n     *\n     * @param pattern the pattern string\n     * @param R the alphabet size\n     */\n    public BoyerMoore(char[] pattern, int R) {\n        this.R = R;\n        this.pattern = new char[pattern.length];\n        for (int j = 0; j < pattern.length; j++)\n            this.pattern[j] = pattern[j];\n\n        // position of rightmost occurrence of c in the pattern\n        right = new int[R];\n        for (int c = 0; c < R; c++)\n            right[c] = -1;\n        for (int j = 0; j < pattern.length; j++)\n            right[pattern[j]] = j;\n    }\n\n    /**\n     * Returns the index of the first occurrence of the pattern string\n     * in the text string.\n     *\n     * @param  txt the text string\n     * @return the index of the first occurrence of the pattern string\n     *         in the text string; n if no such match\n     */\n    public int search(String txt) {\n        int m = pat.length();\n        int n = txt.length();\n        int skip;\n        for (int i = 0; i <= n - m; i += skip) {\n            skip = 0;\n            for (int j = m-1; j >= 0; j--) {\n                if (pat.charAt(j) != txt.charAt(i+j)) {\n                    skip = Math.max(1, j - right[txt.charAt(i+j)]);\n                    break;\n                }\n            }\n            if (skip == 0) return i;    // found\n        }\n        return n;                       // not found\n    }\n\n\n    /**\n     * Returns the index of the first occurrence of the pattern string\n     * in the text string.\n     *\n     * @param  text the text string\n     * @return the index of the first occurrence of the pattern string\n     *         in the text string; n if no such match\n     */\n    public int search(char[] text) {\n        int m = pattern.length;\n        int n = text.length;\n        int skip;\n        for (int i = 0; i <= n - m; i += skip) {\n            skip = 0;\n            for (int j = m-1; j >= 0; j--) {\n                if (pattern[j] != text[i+j]) {\n                    skip = Math.max(1, j - right[text[i+j]]);\n                    break;\n                }\n            }\n            if (skip == 0) return i;    // found\n        }\n        return n;                       // not found\n    }\n\n\n    /**\n     * Takes a pattern string and an input string as command-line arguments;\n     * searches for the pattern string in the text string; and prints\n     * the first occurrence of the pattern string in the text string.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String pat = args[0];\n        String txt = args[1];\n        char[] pattern = pat.toCharArray();\n        char[] text    = txt.toCharArray();\n\n        BoyerMoore boyermoore1 = new BoyerMoore(pat);\n        BoyerMoore boyermoore2 = new BoyerMoore(pattern, 256);\n        int offset1 = boyermoore1.search(txt);\n        int offset2 = boyermoore2.search(text);\n\n        // print results\n        StdOut.println(\"text:    \" + txt);\n\n        StdOut.print(\"pattern: \");\n        for (int i = 0; i < offset1; i++)\n            StdOut.print(\" \");\n        StdOut.println(pat);\n\n        StdOut.print(\"pattern: \");\n        for (int i = 0; i < offset2; i++)\n            StdOut.print(\" \");\n        StdOut.println(pat);\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BreadthFirstDirectedPaths.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BreadthFirstDirectedPaths.java\n *  Execution:    java BreadthFirstDirectedPaths digraph.txt s\n *  Dependencies: Digraph.java Queue.java Stack.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Run breadth-first search on a digraph.\n *  Runs in O(E + V) time.\n *\n *  % java BreadthFirstDirectedPaths tinyDG.txt 3\n *  3 to 0 (2):  3->2->0\n *  3 to 1 (3):  3->2->0->1\n *  3 to 2 (1):  3->2\n *  3 to 3 (0):  3\n *  3 to 4 (2):  3->5->4\n *  3 to 5 (1):  3->5\n *  3 to 6 (-):  not connected\n *  3 to 7 (-):  not connected\n *  3 to 8 (-):  not connected\n *  3 to 9 (-):  not connected\n *  3 to 10 (-):  not connected\n *  3 to 11 (-):  not connected\n *  3 to 12 (-):  not connected\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code BreadthDirectedFirstPaths} class represents a data type for\n *  finding shortest paths (number of edges) from a source vertex <em>s</em>\n *  (or set of source vertices) to every other vertex in the digraph.\n *  <p>\n *  This implementation uses breadth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and <em>E</em> is\n *  the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BreadthFirstDirectedPaths {\n    private static final int INFINITY = Integer.MAX_VALUE;\n    private boolean[] marked;  // marked[v] = is there an s->v path?\n    private int[] edgeTo;      // edgeTo[v] = last edge on shortest s->v path\n    private int[] distTo;      // distTo[v] = length of shortest s->v path\n\n    /**\n     * Computes the shortest path from {@code s} and every other vertex in {@code digraph}.\n     * @param digraph the digraph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public BreadthFirstDirectedPaths(Digraph digraph, int s) {\n        marked = new boolean[digraph.V()];\n        distTo = new int[digraph.V()];\n        edgeTo = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            distTo[v] = INFINITY;\n        validateVertex(s);\n        bfs(digraph, s);\n    }\n\n    /**\n     * Computes the shortest path from any one of the source vertices in {@code sources}\n     * to every other vertex in {@code digraph}.\n     * @param digraph the digraph\n     * @param sources the source vertices\n     * @throws IllegalArgumentException if {@code sources} is {@code null}\n     * @throws IllegalArgumentException if {@code sources} contains no vertices\n     * @throws IllegalArgumentException unless each vertex {@code v} in\n     *         {@code sources} satisfies {@code 0 <= v < V}\n     */\n    public BreadthFirstDirectedPaths(Digraph digraph, Iterable<Integer> sources) {\n        marked = new boolean[digraph.V()];\n        distTo = new int[digraph.V()];\n        edgeTo = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            distTo[v] = INFINITY;\n        validateVertices(sources);\n        bfs(digraph, sources);\n    }\n\n    // BFS from single source\n    private void bfs(Digraph digraph, int s) {\n        Queue<Integer> queue = new Queue<Integer>();\n        marked[s] = true;\n        distTo[s] = 0;\n        queue.enqueue(s);\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : digraph.adj(v)) {\n                if (!marked[w]) {\n                    edgeTo[w] = v;\n                    distTo[w] = distTo[v] + 1;\n                    marked[w] = true;\n                    queue.enqueue(w);\n                }\n            }\n        }\n    }\n\n    // BFS from multiple sources\n    private void bfs(Digraph digraph, Iterable<Integer> sources) {\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int s : sources) {\n            marked[s] = true;\n            distTo[s] = 0;\n            queue.enqueue(s);\n        }\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : digraph.adj(v)) {\n                if (!marked[w]) {\n                    edgeTo[w] = v;\n                    distTo[w] = distTo[v] + 1;\n                    marked[w] = true;\n                    queue.enqueue(w);\n                }\n            }\n        }\n    }\n\n    /**\n     * Is there a directed path from the source {@code s} (or sources) to vertex {@code v}?\n     * @param v the vertex\n     * @return {@code true} if there is a directed path, {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    /**\n     * Returns the number of edges in a shortest path from the source {@code s}\n     * (or sources) to vertex {@code v}?\n     * @param v the vertex\n     * @return the number of edges in such a shortest path\n     *         (or {@code Integer.MAX_VALUE} if there is no such path)\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int distTo(int v) {\n        validateVertex(v);\n        return distTo[v];\n    }\n\n    /**\n     * Returns a shortest path from {@code s} (or sources) to {@code v}, or\n     * {@code null} if no such path.\n     * @param v the vertex\n     * @return the sequence of vertices on a shortest path, as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Integer> pathTo(int v) {\n        validateVertex(v);\n\n        if (!hasPathTo(v)) return null;\n        Stack<Integer> path = new Stack<Integer>();\n        int x;\n        for (x = v; distTo[x] != 0; x = edgeTo[x])\n            path.push(x);\n        path.push(x);\n        return path;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    // throw an IllegalArgumentException if vertices is null, has zero vertices,\n    // or has a vertex not between 0 and V-1\n    private void validateVertices(Iterable<Integer> vertices) {\n        if (vertices == null) {\n            throw new IllegalArgumentException(\"argument is null\");\n        }\n        int vertexCount = 0;\n        for (Integer v : vertices) {\n            vertexCount++;\n            if (v == null) {\n                throw new IllegalArgumentException(\"vertex is null\");\n            }\n            validateVertex(v);\n        }\n        if (vertexCount == 0) {\n            throw new IllegalArgumentException(\"zero vertices\");\n        }\n    }\n\n    /**\n     * Unit tests the {@code BreadthFirstDirectedPaths} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n        // StdOut.println(digraph);\n\n        int s = Integer.parseInt(args[1]);\n        BreadthFirstDirectedPaths bfs = new BreadthFirstDirectedPaths(digraph, s);\n\n        for (int v = 0; v < digraph.V(); v++) {\n            if (bfs.hasPathTo(v)) {\n                StdOut.printf(\"%d to %d (%d):  \", s, v, bfs.distTo(v));\n                for (int x : bfs.pathTo(v)) {\n                    if (x == s) StdOut.print(x);\n                    else        StdOut.print(\"->\" + x);\n                }\n                StdOut.println();\n            }\n\n            else {\n                StdOut.printf(\"%d to %d (-):  not connected\\n\", s, v);\n            }\n\n        }\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/BreadthFirstPaths.java",
    "content": "/******************************************************************************\n *  Compilation:  javac BreadthFirstPaths.java\n *  Execution:    java BreadthFirstPaths G s\n *  Dependencies: Graph.java Queue.java Stack.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyCG.txt\n *                https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *                https://algs4.cs.princeton.edu/41graph/largeG.txt\n *\n *  Run breadth first search on an undirected graph.\n *  Runs in O(E + V) time.\n *\n *  %  java Graph tinyCG.txt\n *  6 8\n *  0: 2 1 5\n *  1: 0 2\n *  2: 0 1 3 4\n *  3: 5 4 2\n *  4: 3 2\n *  5: 3 0\n *\n *  %  java BreadthFirstPaths tinyCG.txt 0\n *  0 to 0 (0):  0\n *  0 to 1 (1):  0-1\n *  0 to 2 (1):  0-2\n *  0 to 3 (2):  0-2-3\n *  0 to 4 (2):  0-2-4\n *  0 to 5 (1):  0-5\n *\n *  %  java BreadthFirstPaths largeG.txt 0\n *  0 to 0 (0):  0\n *  0 to 1 (418):  0-932942-474885-82707-879889-971961-...\n *  0 to 2 (323):  0-460790-53370-594358-780059-287921-...\n *  0 to 3 (168):  0-713461-75230-953125-568284-350405-...\n *  0 to 4 (144):  0-460790-53370-310931-440226-380102-...\n *  0 to 5 (566):  0-932942-474885-82707-879889-971961-...\n *  0 to 6 (349):  0-932942-474885-82707-879889-971961-...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code BreadthFirstPaths} class represents a data type for finding\n *  shortest paths (number of edges) from a source vertex <em>s</em>\n *  (or a set of source vertices)\n *  to every other vertex in an undirected graph.\n *  <p>\n *  This implementation uses breadth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class BreadthFirstPaths {\n    private static final int INFINITY = Integer.MAX_VALUE;\n    private boolean[] marked;  // marked[v] = is there an s-v path\n    private int[] edgeTo;      // edgeTo[v] = previous edge on shortest s-v path\n    private int[] distTo;      // distTo[v] = number of edges shortest s-v path\n\n    /**\n     * Computes the shortest path between the source vertex {@code s}\n     * and every other vertex in the undirected graph {@code graph}.\n     * @param graph the graph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public BreadthFirstPaths(Graph graph, int s) {\n        marked = new boolean[graph.V()];\n        distTo = new int[graph.V()];\n        edgeTo = new int[graph.V()];\n        validateVertex(s);\n        bfs(graph, s);\n\n        assert check(graph, s);\n    }\n\n    /**\n     * Computes the shortest path between any one of the source vertices in {@code sources}\n     * and every other vertex in {@code graph}.\n     * @param graph the graph\n     * @param sources the source vertices\n     * @throws IllegalArgumentException if {@code sources} is {@code null}\n     * @throws IllegalArgumentException if {@code sources} contains no vertices\n     * @throws IllegalArgumentException unless {@code 0 <= s < V} for each vertex\n     *         {@code s} in {@code sources}\n     */\n    public BreadthFirstPaths(Graph graph, Iterable<Integer> sources) {\n        marked = new boolean[graph.V()];\n        distTo = new int[graph.V()];\n        edgeTo = new int[graph.V()];\n        for (int v = 0; v < graph.V(); v++)\n            distTo[v] = INFINITY;\n        validateVertices(sources);\n        bfs(graph, sources);\n    }\n\n\n    // breadth-first search from a single source\n    private void bfs(Graph graph, int s) {\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int v = 0; v < graph.V(); v++)\n            distTo[v] = INFINITY;\n        distTo[s] = 0;\n        marked[s] = true;\n        queue.enqueue(s);\n\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : graph.adj(v)) {\n                if (!marked[w]) {\n                    edgeTo[w] = v;\n                    distTo[w] = distTo[v] + 1;\n                    marked[w] = true;\n                    queue.enqueue(w);\n                }\n            }\n        }\n    }\n\n    // breadth-first search from multiple sources\n    private void bfs(Graph graph, Iterable<Integer> sources) {\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int s : sources) {\n            marked[s] = true;\n            distTo[s] = 0;\n            queue.enqueue(s);\n        }\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : graph.adj(v)) {\n                if (!marked[w]) {\n                    edgeTo[w] = v;\n                    distTo[w] = distTo[v] + 1;\n                    marked[w] = true;\n                    queue.enqueue(w);\n                }\n            }\n        }\n    }\n\n    /**\n     * Is there a path between the source vertex {@code s} (or sources) and vertex {@code v}?\n     * @param v the vertex\n     * @return {@code true} if there is a path, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    /**\n     * Returns the number of edges in a shortest path between the source vertex {@code s}\n     * (or sources) and vertex {@code v}?\n     * @param v the vertex\n     * @return the number of edges in such a shortest path\n     *         (or {@code Integer.MAX_VALUE} if there is no such path)\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int distTo(int v) {\n        validateVertex(v);\n        return distTo[v];\n    }\n\n    /**\n     * Returns a shortest path between the source vertex {@code s} (or sources)\n     * and {@code v}, or {@code null} if no such path.\n     * @param  v the vertex\n     * @return the sequence of vertices on a shortest path, as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Integer> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<Integer> path = new Stack<Integer>();\n        int x;\n        for (x = v; distTo[x] != 0; x = edgeTo[x])\n            path.push(x);\n        path.push(x);\n        return path;\n    }\n\n\n    // check optimality conditions for single source\n    private boolean check(Graph graph, int s) {\n\n        // check that the distance of s = 0\n        if (distTo[s] != 0) {\n            StdOut.println(\"distance of source \" + s + \" to itself = \" + distTo[s]);\n            return false;\n        }\n\n        // check that for each edge v-w dist[w] <= dist[v] + 1\n        // provided v is reachable from s\n        for (int v = 0; v < graph.V(); v++) {\n            for (int w : graph.adj(v)) {\n                if (hasPathTo(v) != hasPathTo(w)) {\n                    StdOut.println(\"edge \" + v + \"-\" + w);\n                    StdOut.println(\"hasPathTo(\" + v + \") = \" + hasPathTo(v));\n                    StdOut.println(\"hasPathTo(\" + w + \") = \" + hasPathTo(w));\n                    return false;\n                }\n                if (hasPathTo(v) && (distTo[w] > distTo[v] + 1)) {\n                    StdOut.println(\"edge \" + v + \"-\" + w);\n                    StdOut.println(\"distTo[\" + v + \"] = \" + distTo[v]);\n                    StdOut.println(\"distTo[\" + w + \"] = \" + distTo[w]);\n                    return false;\n                }\n            }\n        }\n\n        // check that v = edgeTo[w] satisfies distTo[w] = distTo[v] + 1\n        // provided v is reachable from s\n        for (int w = 0; w < graph.V(); w++) {\n            if (!hasPathTo(w) || w == s) continue;\n            int v = edgeTo[w];\n            if (distTo[w] != distTo[v] + 1) {\n                StdOut.println(\"shortest path edge \" + v + \"-\" + w);\n                StdOut.println(\"distTo[\" + v + \"] = \" + distTo[v]);\n                StdOut.println(\"distTo[\" + w + \"] = \" + distTo[w]);\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    // throw an IllegalArgumentException if vertices is null, has zero vertices,\n    // or has a vertex not between 0 and V-1\n    private void validateVertices(Iterable<Integer> vertices) {\n        if (vertices == null) {\n            throw new IllegalArgumentException(\"argument is null\");\n        }\n        int vertexCount = 0;\n        for (Integer v : vertices) {\n            vertexCount++;\n            if (v == null) {\n                throw new IllegalArgumentException(\"vertex is null\");\n            }\n            validateVertex(v);\n        }\n        if (vertexCount == 0) {\n            throw new IllegalArgumentException(\"zero vertices\");\n        }\n    }\n\n    /**\n     * Unit tests the {@code BreadthFirstPaths} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        // StdOut.println(graph);\n\n        int s = Integer.parseInt(args[1]);\n        BreadthFirstPaths bfs = new BreadthFirstPaths(graph, s);\n\n        for (int v = 0; v < graph.V(); v++) {\n            if (bfs.hasPathTo(v)) {\n                StdOut.printf(\"%d to %d (%d):  \", s, v, bfs.distTo(v));\n                for (int x : bfs.pathTo(v)) {\n                    if (x == s) StdOut.print(x);\n                    else        StdOut.print(\"-\" + x);\n                }\n                StdOut.println();\n            }\n\n            else {\n                StdOut.printf(\"%d to %d (-):  not connected\\n\", s, v);\n            }\n\n        }\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/CC.java",
    "content": "/******************************************************************************\n *  Compilation:  javac CC.java\n *  Execution:    java CC filename.txt\n *  Dependencies: Graph.java StdOut.java Queue.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *                https://algs4.cs.princeton.edu/41graph/largeG.txt\n *\n *  Compute connected components using depth first search.\n *  Runs in O(E + V) time.\n *\n *  % java CC tinyG.txt\n *  3 components\n *  0 1 2 3 4 5 6\n *  7 8\n *  9 10 11 12\n *\n *  % java CC mediumG.txt\n *  1 components\n *  0 1 2 3 4 5 6 7 8 9 10 ...\n *\n *  % java -Xss50m CC largeG.txt\n *  1 components\n *  0 1 2 3 4 5 6 7 8 9 10 ...\n *\n *  Note: This implementation uses a recursive DFS. To avoid needing\n *        a potentially very large stack size, replace with a nonrecursive\n *        DFS ala NonrecursiveDFS.java.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code CC} class represents a data type for\n *  determining the connected components in an undirected graph.\n *  The <em>id</em> operation determines in which connected component\n *  a given vertex lies; the <em>connected</em> operation\n *  determines whether two vertices are in the same connected component;\n *  the <em>count</em> operation determines the number of connected\n *  components; and the <em>size</em> operation determines the number\n *  of vertices in the connect component containing a given vertex.\n *  <p>\n *  The <em>component identifier</em> of a vertex is an integer between\n *  0 and <em>k</em>–1, where <em>k</em> is the number of connected components.\n *  Two vertices have the same component identifier if and only if\n *  they are in the same connected component.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time,\n *  where <em>V</em> is the number of vertices and <em>E</em> is the\n *  number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <em>Algorithms, 4th Edition</em> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class CC {\n    private boolean[] marked;   // marked[v] = has vertex v been marked?\n    private int[] id;           // id[v] = id of connected component containing v\n    private int[] size;         // size[id] = number of vertices in given component\n    private int count;          // number of connected components\n\n    /**\n     * Computes the connected components of the undirected graph {@code graph}.\n     *\n     * @param graph the undirected graph\n     */\n    public CC(Graph graph) {\n        marked = new boolean[graph.V()];\n        id = new int[graph.V()];\n        size = new int[graph.V()];\n        for (int v = 0; v < graph.V(); v++) {\n            if (!marked[v]) {\n                dfs(graph, v);\n                count++;\n            }\n        }\n    }\n\n    /**\n     * Computes the connected components of the edge-weighted graph {@code graph}.\n     *\n     * @param graph the edge-weighted graph\n     */\n    public CC(EdgeWeightedGraph graph) {\n        marked = new boolean[graph.V()];\n        id = new int[graph.V()];\n        size = new int[graph.V()];\n        for (int v = 0; v < graph.V(); v++) {\n            if (!marked[v]) {\n                dfs(graph, v);\n                count++;\n            }\n        }\n    }\n\n    // depth-first search for a Graph\n    private void dfs(Graph graph, int v) {\n        marked[v] = true;\n        id[v] = count;\n        size[count]++;\n        for (int w : graph.adj(v)) {\n            if (!marked[w]) {\n                dfs(graph, w);\n            }\n        }\n    }\n\n    // depth-first search for an EdgeWeightedGraph\n    private void dfs(EdgeWeightedGraph graph, int v) {\n        marked[v] = true;\n        id[v] = count;\n        size[count]++;\n        for (Edge e : graph.adj(v)) {\n            int w = e.other(v);\n            if (!marked[w]) {\n                dfs(graph, w);\n            }\n        }\n    }\n\n\n    /**\n     * Returns the component id of the connected component containing vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the component id of the connected component containing vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int id(int v) {\n        validateVertex(v);\n        return id[v];\n    }\n\n    /**\n     * Returns the number of vertices in the connected component containing vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the number of vertices in the connected component containing vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int size(int v) {\n        validateVertex(v);\n        return size[id[v]];\n    }\n\n    /**\n     * Returns the number of connected components in the graph {@code G}.\n     *\n     * @return the number of connected components in the graph {@code G}\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Returns true if vertices {@code v} and {@code w} are in the same\n     * connected component.\n     *\n     * @param  v one vertex\n     * @param  w the other vertex\n     * @return {@code true} if vertices {@code v} and {@code w} are in the same\n     *         connected component; {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws IllegalArgumentException unless {@code 0 <= w < V}\n     */\n    public boolean connected(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        return id(v) == id(w);\n    }\n\n    /**\n     * Returns true if vertices {@code v} and {@code w} are in the same\n     * connected component.\n     *\n     * @param  v one vertex\n     * @param  w the other vertex\n     * @return {@code true} if vertices {@code v} and {@code w} are in the same\n     *         connected component; {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws IllegalArgumentException unless {@code 0 <= w < V}\n     * @deprecated Replaced by {@link #connected(int, int)}.\n     */\n    @Deprecated\n    public boolean areConnected(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        return id(v) == id(w);\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code CC} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        CC cc = new CC(graph);\n\n        // number of connected components\n        int m = cc.count();\n        StdOut.println(m + \" components\");\n\n        // compute list of vertices in each connected component\n        Queue<Integer>[] components = (Queue<Integer>[]) new Queue[m];\n        for (int i = 0; i < m; i++) {\n            components[i] = new Queue<Integer>();\n        }\n        for (int v = 0; v < graph.V(); v++) {\n            components[cc.id(v)].enqueue(v);\n        }\n\n        // print results\n        for (int i = 0; i < m; i++) {\n            for (int v : components[i]) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/CPM.java",
    "content": "/******************************************************************************\n *  Compilation:  javac CPM.java\n *  Execution:    java CPM < input.txt\n *  Dependencies: EdgeWeightedDigraph.java AcyclicDigraphLP.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/44sp/jobsPC.txt\n *\n *  Critical path method.\n *\n *  % java CPM < jobsPC.txt\n *   job   start  finish\n *  --------------------\n *     0     0.0    41.0\n *     1    41.0    92.0\n *     2   123.0   173.0\n *     3    91.0   127.0\n *     4    70.0   108.0\n *     5     0.0    45.0\n *     6    70.0    91.0\n *     7    41.0    73.0\n *     8    91.0   123.0\n *     9    41.0    70.0\n *  Finish time:   173.0\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code CPM} class provides a client that solves the\n *  parallel precedence-constrained job scheduling problem\n *  via the <em>critical path method</em>. It reduces the problem\n *  to the longest-paths problem in edge-weighted DAGs.\n *  It builds an edge-weighted digraph (which must be a DAG)\n *  from the job-scheduling problem specification,\n *  finds the longest-paths tree, and computes the longest-paths\n *  lengths (which are precisely the start times for each job).\n *  <p>\n *  This implementation uses {@link AcyclicLP} to find a longest\n *  path in a DAG.\n *  The program takes &Theta;(<em>V</em> + <em>E</em>) time in\n *  the worst case, where <em>V</em> is the number of jobs and\n *  <em>E</em> is the number of precedence constraints.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class CPM {\n\n    // this class cannot be instantiated\n    private CPM() { }\n\n    /**\n     *  Reads the precedence constraints from standard input\n     *  and prints a feasible schedule to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // number of jobs\n        int n = StdIn.readInt();\n\n        // source and sink\n        int source = 2*n;\n        int sink   = 2*n + 1;\n\n        // build network\n        EdgeWeightedDigraph G = new EdgeWeightedDigraph(2*n + 2);\n        for (int i = 0; i < n; i++) {\n            double duration = StdIn.readDouble();\n            G.addEdge(new DirectedEdge(source, i, 0.0));\n            G.addEdge(new DirectedEdge(i+n, sink, 0.0));\n            G.addEdge(new DirectedEdge(i, i+n,    duration));\n\n            // precedence constraints\n            int m = StdIn.readInt();\n            for (int j = 0; j < m; j++) {\n                int precedent = StdIn.readInt();\n                G.addEdge(new DirectedEdge(n+i, precedent, 0.0));\n            }\n        }\n\n        // compute longest path\n        AcyclicLP lp = new AcyclicLP(G, source);\n\n        // print results\n        StdOut.println(\" job   start  finish\");\n        StdOut.println(\"--------------------\");\n        for (int i = 0; i < n; i++) {\n            StdOut.printf(\"%4d %7.1f %7.1f\\n\", i, lp.distTo(i), lp.distTo(i+n));\n        }\n        StdOut.printf(\"Finish time: %7.1f\\n\", lp.distTo(sink));\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Cat.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Cat.java\n *  Execution:    java Cat input0.txt input1.txt ... output.txt\n *  Dependencies: In.java Out.java\n *  Data files:   https://algs4.cs.princeton.edu/11model/in1.txt\n *                https://algs4.cs.princeton.edu/11model/in2.txt\n *\n *  Reads in text files specified as the first command-line\n *  arguments, concatenates them, and writes the result to\n *  filename specified as the last command-line arguments.\n *\n *  % more in1.txt\n *  This is\n *\n *  % more in2.txt\n *  a tiny\n *  test.\n *\n *  % java Cat in1.txt in2.txt out.txt\n *\n *  % more out.txt\n *  This is\n *  a tiny\n *  test.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Cat} class provides a client for concatenating the results\n *  of several text files.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/11model\">Section 1.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Cat {\n\n    // this class should not be instantiated\n    private Cat() { }\n\n    /**\n     * Reads in a sequence of text files specified as the first command-line\n     * arguments, concatenates them, and writes the results to the file\n     * specified as the last command-line argument.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Out out = new Out(args[args.length - 1]);\n        for (int i = 0; i < args.length - 1; i++) {\n            In in = new In(args[i]);\n            String s = in.readAll();\n            out.println(s);\n            in.close();\n        }\n        out.close();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ClosestPair.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ClosestPair.java\n *  Execution:    java ClosestPair < input.txt\n *  Dependencies: Point2D.java\n *  Data files:   https://algs4.cs.princeton.edu/99hull/rs1423.txt\n *                https://algs4.cs.princeton.edu/99hull/kw1260.txt\n *\n *  Given n points in the plane, find the closest pair in n log n time.\n *\n *  Note: could speed it up by comparing square of Euclidean distances\n *  instead of Euclidean distances.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n *  The {@code ClosestPair} data type computes a closest pair of points\n *  in a set of <em>n</em> points in the plane and provides accessor methods\n *  for getting the closest pair of points and the distance between them.\n *  The distance between two points is their Euclidean distance.\n *  <p>\n *  This implementation uses a divide-and-conquer algorithm.\n *  It runs in O(<em>n</em> log <em>n</em>) time in the worst case and uses\n *  O(<em>n</em>) extra space.\n *  <p>\n *  See also {@link FarthestPair}.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/99hull\">Section 9.9</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class ClosestPair {\n\n    // closest pair of points and their Euclidean distance\n    private Point2D best1, best2;\n    private double bestDistance = Double.POSITIVE_INFINITY;\n\n    /**\n     * Computes the closest pair of points in the specified array of points.\n     *\n     * @param  points the array of points\n     * @throws IllegalArgumentException if {@code points} is {@code null} or if any\n     *         entry in {@code points[]} is {@code null}\n     */\n    public ClosestPair(Point2D[] points) {\n        if (points == null) throw new IllegalArgumentException(\"constructor argument is null\");\n        for (int i = 0; i < points.length; i++) {\n            if (points[i] == null) throw new IllegalArgumentException(\"array element \" + i + \" is null\");\n        }\n\n        int n = points.length;\n        if (n <= 1) return;\n\n        // sort by x-coordinate (breaking ties by y-coordinate via stability)\n        Point2D[] pointsByX = new Point2D[n];\n        for (int i = 0; i < n; i++)\n            pointsByX[i] = points[i];\n        Arrays.sort(pointsByX, Point2D.Y_ORDER);\n        Arrays.sort(pointsByX, Point2D.X_ORDER);\n\n        // check for coincident points\n        for (int i = 0; i < n-1; i++) {\n            if (pointsByX[i].equals(pointsByX[i+1])) {\n                bestDistance = 0.0;\n                best1 = pointsByX[i];\n                best2 = pointsByX[i+1];\n                return;\n            }\n        }\n\n        // sort by y-coordinate (but not yet sorted)\n        Point2D[] pointsByY = new Point2D[n];\n        for (int i = 0; i < n; i++)\n            pointsByY[i] = pointsByX[i];\n\n        // auxiliary array\n        Point2D[] aux = new Point2D[n];\n\n        closest(pointsByX, pointsByY, aux, 0, n-1);\n    }\n\n    // find closest pair of points in pointsByX[lo..hi]\n    // precondition:  pointsByX[lo..hi] and pointsByY[lo..hi] are the same sequence of points\n    // precondition:  pointsByX[lo..hi] sorted by x-coordinate\n    // postcondition: pointsByY[lo..hi] sorted by y-coordinate\n    private double closest(Point2D[] pointsByX, Point2D[] pointsByY, Point2D[] aux, int lo, int hi) {\n        if (hi <= lo) return Double.POSITIVE_INFINITY;\n\n        int mid = lo + (hi - lo) / 2;\n        Point2D median = pointsByX[mid];\n\n        // compute closest pair with both endpoints in left subarray or both in right subarray\n        double delta1 = closest(pointsByX, pointsByY, aux, lo, mid);\n        double delta2 = closest(pointsByX, pointsByY, aux, mid+1, hi);\n        double delta = Math.min(delta1, delta2);\n\n        // merge back so that pointsByY[lo..hi] are sorted by y-coordinate\n        merge(pointsByY, aux, lo, mid, hi);\n\n        // aux[0..m-1] = sequence of points closer than delta, sorted by y-coordinate\n        int m = 0;\n        for (int i = lo; i <= hi; i++) {\n            if (Math.abs(pointsByY[i].x() - median.x()) < delta)\n                aux[m++] = pointsByY[i];\n        }\n\n        // compare each point to its neighbors with y-coordinate closer than delta\n        for (int i = 0; i < m; i++) {\n            // a geometric packing argument shows that this loop iterates at most 7 times\n            for (int j = i+1; (j < m) && (aux[j].y() - aux[i].y() < delta); j++) {\n                double distance = aux[i].distanceTo(aux[j]);\n                if (distance < delta) {\n                    delta = distance;\n                    if (distance < bestDistance) {\n                        bestDistance = delta;\n                        best1 = aux[i];\n                        best2 = aux[j];\n                        // StdOut.println(\"better distance = \" + delta + \" from \" + best1 + \" to \" + best2);\n                    }\n                }\n            }\n        }\n        return delta;\n    }\n\n    /**\n     * Returns one of the points in the closest pair of points.\n     *\n     * @return one of the two points in the closest pair of points;\n     *         {@code null} if no such point (because there are fewer than 2 points)\n     */\n    public Point2D either() {\n        return best1;\n    }\n\n    /**\n     * Returns the other point in the closest pair of points.\n     *\n     * @return the other point in the closest pair of points\n     *         {@code null} if no such point (because there are fewer than 2 points)\n     */\n    public Point2D other() {\n        return best2;\n    }\n\n    /**\n     * Returns the Euclidean distance between the closest pair of points.\n     *\n     * @return the Euclidean distance between the closest pair of points\n     *         {@code Double.POSITIVE_INFINITY} if no such pair of points\n     *         exist (because there are fewer than 2 points)\n     */\n    public double distance() {\n        return bestDistance;\n    }\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]\n    // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays\n    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {\n        // copy to aux[]\n        for (int k = lo; k <= hi; k++) {\n            aux[k] = a[k];\n        }\n\n        // merge back to a[]\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)              a[k] = aux[j++];\n            else if (j > hi)               a[k] = aux[i++];\n            else if (less(aux[j], aux[i])) a[k] = aux[j++];\n            else                           a[k] = aux[i++];\n        }\n    }\n\n\n\n   /**\n     * Unit tests the {@code ClosestPair} data type.\n     * Reads in an integer {@code n} and {@code n} points (specified by\n     * their <em>x</em>- and <em>y</em>-coordinates) from standard input;\n     * computes a closest pair of points; and prints the pair to standard\n     * output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        Point2D[] points = new Point2D[n];\n        for (int i = 0; i < n; i++) {\n            double x = StdIn.readDouble();\n            double y = StdIn.readDouble();\n            points[i] = new Point2D(x, y);\n        }\n        ClosestPair closest = new ClosestPair(points);\n        StdOut.println(closest.distance() + \" from \" + closest.either() + \" to \" + closest.other());\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/CollisionSystem.java",
    "content": "/******************************************************************************\n *  Compilation:  javac CollisionSystem.java\n *  Execution:    java CollisionSystem n               (n random particles)\n *                java CollisionSystem < input.txt     (from a file)\n *  Dependencies: StdDraw.java Particle.java MinPQ.java\n *  Data files:   https://algs4.cs.princeton.edu/61event/diffusion.txt\n *                https://algs4.cs.princeton.edu/61event/diffusion2.txt\n *                https://algs4.cs.princeton.edu/61event/diffusion3.txt\n *                https://algs4.cs.princeton.edu/61event/brownian.txt\n *                https://algs4.cs.princeton.edu/61event/brownian2.txt\n *                https://algs4.cs.princeton.edu/61event/billiards5.txt\n *                https://algs4.cs.princeton.edu/61event/pendulum.txt\n *\n *  Creates n random particles and simulates their motion according\n *  to the laws of elastic collisions.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.Color;\n\n/**\n *  The {@code CollisionSystem} class represents a collection of particles\n *  moving in the unit box, according to the laws of elastic collision.\n *  This event-based simulation relies on a priority queue.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/61event\">Section 6.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class CollisionSystem {\n    private static final double HZ = 0.5;    // number of redraw events per clock tick\n\n    private MinPQ<Event> pq;          // the priority queue\n    private double t  = 0.0;          // simulation clock time\n    private Particle[] particles;     // the array of particles\n\n    /**\n     * Initializes a system with the specified collection of particles.\n     * The individual particles will be mutated during the simulation.\n     *\n     * @param  particles the array of particles\n     */\n    public CollisionSystem(Particle[] particles) {\n        this.particles = particles.clone();   // defensive copy\n    }\n\n    // updates priority queue with all new events for particle a\n    private void predict(Particle a, double limit) {\n        if (a == null) return;\n\n        // particle-particle collisions\n        for (int i = 0; i < particles.length; i++) {\n            double dt = a.timeToHit(particles[i]);\n            if (t + dt <= limit)\n                pq.insert(new Event(t + dt, a, particles[i]));\n        }\n\n        // particle-wall collisions\n        double dtX = a.timeToHitVerticalWall();\n        double dtY = a.timeToHitHorizontalWall();\n        if (t + dtX <= limit) pq.insert(new Event(t + dtX, a, null));\n        if (t + dtY <= limit) pq.insert(new Event(t + dtY, null, a));\n    }\n\n    // redraw all particles\n    private void redraw(double limit) {\n        StdDraw.clear();\n        for (int i = 0; i < particles.length; i++) {\n            particles[i].draw();\n        }\n        StdDraw.show();\n        StdDraw.pause(20);\n        if (t < limit) {\n            pq.insert(new Event(t + 1.0 / HZ, null, null));\n        }\n    }\n\n\n    /**\n     * Simulates the system of particles for the specified amount of time.\n     *\n     * @param  limit the amount of time\n     */\n    public void simulate(double limit) {\n\n        // initialize PQ with collision events and redraw event\n        pq = new MinPQ<Event>();\n        for (int i = 0; i < particles.length; i++) {\n            predict(particles[i], limit);\n        }\n        pq.insert(new Event(0, null, null));        // redraw event\n\n\n        // the main event-driven simulation loop\n        while (!pq.isEmpty()) {\n\n            // get impending event, discard if invalidated\n            Event e = pq.delMin();\n            if (!e.isValid()) continue;\n            Particle a = e.a;\n            Particle b = e.b;\n\n            // physical collision, so update positions, and then simulation clock\n            for (int i = 0; i < particles.length; i++)\n                particles[i].move(e.time - t);\n            t = e.time;\n\n            // process event\n            if      (a != null && b != null) a.bounceOff(b);              // particle-particle collision\n            else if (a != null && b == null) a.bounceOffVerticalWall();   // particle-wall collision\n            else if (a == null && b != null) b.bounceOffHorizontalWall(); // particle-wall collision\n            else if (a == null && b == null) redraw(limit);               // redraw event\n\n            // update the priority queue with new collisions involving a or b\n            predict(a, limit);\n            predict(b, limit);\n        }\n    }\n\n\n   /***************************************************************************\n    *  An event during a particle collision simulation. Each event contains\n    *  the time at which it will occur (assuming no supervening actions)\n    *  and the particles a and b involved.\n    *\n    *    -  a and b both null:      redraw event\n    *    -  a null, b not null:     collision with vertical wall\n    *    -  a not null, b null:     collision with horizontal wall\n    *    -  a and b both not null:  binary collision between a and b\n    *\n    ***************************************************************************/\n    private static class Event implements Comparable<Event> {\n        private final double time;         // time that event is scheduled to occur\n        private final Particle a, b;       // particles involved in event, possibly null\n        private final int countA, countB;  // collision counts at event creation\n\n\n        // create a new event to occur at time t involving a and b\n        public Event(double t, Particle a, Particle b) {\n            this.time = t;\n            this.a    = a;\n            this.b    = b;\n            if (a != null) countA = a.count();\n            else           countA = -1;\n            if (b != null) countB = b.count();\n            else           countB = -1;\n        }\n\n        // compare times when two events will occur\n        public int compareTo(Event that) {\n            return Double.compare(this.time, that.time);\n        }\n\n        // has any collision occurred between when event was created and now?\n        public boolean isValid() {\n            if (a != null && a.count() != countA) return false;\n            if (b != null && b.count() != countB) return false;\n            return true;\n        }\n\n    }\n\n\n    /**\n     * Unit tests the {@code CollisionSystem} data type.\n     * Reads in the particle collision system from a standard input\n     * (or generates {@code N} random particles if a command-line integer\n     * is specified); simulates the system.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        StdDraw.setCanvasSize(600, 600);\n\n        // enable double buffering\n        StdDraw.enableDoubleBuffering();\n\n        // the array of particles\n        Particle[] particles;\n\n        // create n random particles\n        if (args.length == 1) {\n            int n = Integer.parseInt(args[0]);\n            particles = new Particle[n];\n            for (int i = 0; i < n; i++)\n                particles[i] = new Particle();\n        }\n\n        // or read from standard input\n        else {\n            int n = StdIn.readInt();\n            particles = new Particle[n];\n            for (int i = 0; i < n; i++) {\n                double rx     = StdIn.readDouble();\n                double ry     = StdIn.readDouble();\n                double vx     = StdIn.readDouble();\n                double vy     = StdIn.readDouble();\n                double radius = StdIn.readDouble();\n                double mass   = StdIn.readDouble();\n                int r         = StdIn.readInt();\n                int g         = StdIn.readInt();\n                int b         = StdIn.readInt();\n                Color color   = new Color(r, g, b);\n                particles[i] = new Particle(rx, ry, vx, vy, radius, mass, color);\n            }\n        }\n\n        // create collision system and simulate\n        CollisionSystem system = new CollisionSystem(particles);\n        system.simulate(10000);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Complex.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Complex.java\n *  Execution:    java Complex\n *  Dependencies: StdOut.java\n *\n *  Data type for complex numbers.\n *\n *  The data type is \"immutable\" so once you create and initialize\n *  a Complex object, you cannot change it. The \"final\" keyword\n *  when declaring re and im enforces this rule, making it a\n *  compile-time error to change the .re or .im fields after\n *  they've been initialized.\n *\n *  % java Complex\n *  a            = 5.0 + 6.0i\n *  b            = -3.0 + 4.0i\n *  Re(a)        = 5.0\n *  Im(a)        = 6.0\n *  b + a        = 2.0 + 10.0i\n *  a - b        = 8.0 + 2.0i\n *  a * b        = -39.0 + 2.0i\n *  b * a        = -39.0 + 2.0i\n *  a / b        = 0.36 - 1.52i\n *  (a / b) * b  = 5.0 + 6.0i\n *  conj(a)      = 5.0 - 6.0i\n *  |a|          = 7.810249675906654\n *  tan(a)       = -6.685231390246571E-6 + 1.0000103108981198i\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Complex} class represents a complex number.\n *  Complex numbers are immutable: their values cannot be changed after they\n *  are created.\n *  It includes methods for addition, subtraction, multiplication, division,\n *  conjugation, and other common functions on complex numbers.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  In practice, there will be floating-point rounding error.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/99scientific\">Section 9.9</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Complex {\n    private final double re;   // the real part\n    private final double im;   // the imaginary part\n\n    /**\n     * Initializes a complex number from the specified real and imaginary parts.\n     *\n     * @param real the real part\n     * @param imag the imaginary part\n     */\n    public Complex(double real, double imag) {\n        re = real;\n        im = imag;\n    }\n\n    /**\n     * Returns a string representation of this complex number.\n     *\n     * @return a string representation of this complex number,\n     *         of the form 34 - 56i.\n     */\n    public String toString() {\n        if (im == 0) return re + \"\";\n        if (re == 0) return im + \"i\";\n        if (im <  0) return re + \" - \" + (-im) + \"i\";\n        return re + \" + \" + im + \"i\";\n    }\n\n    /**\n     * Returns the absolute value of this complex number.\n     * This quantity is also known as the <em>modulus</em> or <em>magnitude</em>.\n     *\n     * @return the absolute value of this complex number\n     */\n    public double abs() {\n        return Math.hypot(re, im);\n    }\n\n    /**\n     * Returns the phase of this complex number.\n     * This quantity is also known as the <em>angle</em> or <em>argument</em>.\n     *\n     * @return the phase of this complex number, a real number between -pi and pi\n     */\n    public double phase() {\n        return Math.atan2(im, re);\n    }\n\n    /**\n     * Returns the sum of this complex number and the specified complex number.\n     *\n     * @param  that the other complex number\n     * @return the complex number whose value is {@code (this + that)}\n     */\n    public Complex plus(Complex that) {\n        double real = this.re + that.re;\n        double imag = this.im + that.im;\n        return new Complex(real, imag);\n    }\n\n    /**\n     * Returns the result of subtracting the specified complex number from\n     * this complex number.\n     *\n     * @param  that the other complex number\n     * @return the complex number whose value is {@code (this - that)}\n     */\n    public Complex minus(Complex that) {\n        double real = this.re - that.re;\n        double imag = this.im - that.im;\n        return new Complex(real, imag);\n    }\n\n    /**\n     * Returns the product of this complex number and the specified complex number.\n     *\n     * @param  that the other complex number\n     * @return the complex number whose value is {@code (this * that)}\n     */\n    public Complex times(Complex that) {\n        double real = this.re * that.re - this.im * that.im;\n        double imag = this.re * that.im + this.im * that.re;\n        return new Complex(real, imag);\n    }\n\n    /**\n     * Returns the product of this complex number and the specified scalar.\n     *\n     * @param  alpha the scalar\n     * @return the complex number whose value is {@code (alpha * this)}\n     */\n    public Complex scale(double alpha) {\n        return new Complex(alpha * re, alpha * im);\n    }\n\n    /**\n     * Returns the product of this complex number and the specified scalar.\n     *\n     * @param  alpha the scalar\n     * @return the complex number whose value is {@code (alpha * this)}\n     * @deprecated Replaced by {@link #scale(double)}.\n     */\n    @Deprecated\n    public Complex times(double alpha) {\n        return new Complex(alpha * re, alpha * im);\n    }\n\n    /**\n     * Returns the complex conjugate of this complex number.\n     *\n     * @return the complex conjugate of this complex number\n     */\n    public Complex conjugate() {\n        return new Complex(re, -im);\n    }\n\n    /**\n     * Returns the reciprocal of this complex number.\n     *\n     * @return the complex number whose value is {@code (1 / this)}\n     */\n    public Complex reciprocal() {\n        double scale = re*re + im*im;\n        return new Complex(re / scale, -im / scale);\n    }\n\n    /**\n     * Returns the real part of this complex number.\n     *\n     * @return the real part of this complex number\n     */\n    public double re() {\n        return re;\n    }\n\n    /**\n     * Returns the imaginary part of this complex number.\n     *\n     * @return the imaginary part of this complex number\n     */\n    public double im() {\n        return im;\n    }\n\n    /**\n     * Returns the result of dividing the specified complex number into\n     * this complex number.\n     *\n     * @param  that the other complex number\n     * @return the complex number whose value is {@code (this / that)}\n     */\n    public Complex divides(Complex that) {\n        return this.times(that.reciprocal());\n    }\n\n    /**\n     * Returns the complex exponential of this complex number.\n     *\n     * @return the complex exponential of this complex number\n     */\n    public Complex exp() {\n        return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));\n    }\n\n    /**\n     * Returns the complex sine of this complex number.\n     *\n     * @return the complex sine of this complex number\n     */\n    public Complex sin() {\n        return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));\n    }\n\n    /**\n     * Returns the complex cosine of this complex number.\n     *\n     * @return the complex cosine of this complex number\n     */\n    public Complex cos() {\n        return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));\n    }\n\n    /**\n     * Returns the complex tangent of this complex number.\n     *\n     * @return the complex tangent of this complex number\n     */\n    public Complex tan() {\n        return sin().divides(cos());\n    }\n\n\n    /**\n     * Unit tests the {@code Complex} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Complex a = new Complex(5.0, 6.0);\n        Complex b = new Complex(-3.0, 4.0);\n\n        StdOut.println(\"a            = \" + a);\n        StdOut.println(\"b            = \" + b);\n        StdOut.println(\"Re(a)        = \" + a.re());\n        StdOut.println(\"Im(a)        = \" + a.im());\n        StdOut.println(\"b + a        = \" + b.plus(a));\n        StdOut.println(\"a - b        = \" + a.minus(b));\n        StdOut.println(\"a * b        = \" + a.times(b));\n        StdOut.println(\"b * a        = \" + b.times(a));\n        StdOut.println(\"a / b        = \" + a.divides(b));\n        StdOut.println(\"(a / b) * b  = \" + a.divides(b).times(b));\n        StdOut.println(\"conj(a)      = \" + a.conjugate());\n        StdOut.println(\"|a|          = \" + a.abs());\n        StdOut.println(\"tan(a)       = \" + a.tan());\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Count.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Count.java\n *  Execution:    java Count alpha < input.txt\n *  Dependencies: Alphabet.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/50strings/abra.txt\n *                https://algs4.cs.princeton.edu/50strings/pi.txt\n *\n *  Create an alphabet specified on the command line, read in a\n *  sequence of characters over that alphabet (ignoring characters\n *  not in the alphabet), computes the frequency of occurrence of\n *  each character, and print out the results.\n *\n *  %  java Count ABCDR < abra.txt\n *  A 5\n *  B 2\n *  C 1\n *  D 1\n *  R 2\n *\n *  % java Count 0123456789 < pi.txt\n *  0 99959\n *  1 99757\n *  2 100026\n *  3 100230\n *  4 100230\n *  5 100359\n *  6 99548\n *  7 99800\n *  8 99985\n *  9 100106\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code Count} class provides an {@link Alphabet} client for reading\n *  in a piece of text and computing the frequency of occurrence of each\n *  character over a given alphabet.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compress\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Count {\n\n    // Do not instantiate.\n    private Count() { }\n\n    /**\n     * Reads in text from standard input; calculates the frequency of\n     * occurrence of each character over the alphabet specified as a\n     * command-line argument; and prints the frequencies to standard\n     * output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Alphabet alphabet = new Alphabet(args[0]);\n        final int R = alphabet.radix();\n        int[] count = new int[R];\n        while (StdIn.hasNextChar()) {\n            char c = StdIn.readChar();\n            if (alphabet.contains(c))\n                count[alphabet.toIndex(c)]++;\n        }\n        for (int c = 0; c < R; c++)\n            StdOut.println(alphabet.toChar(c) + \" \" + count[c]);\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Counter.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Counter.java\n *  Execution:    java Counter n trials\n *  Dependencies: StdRandom.java StdOut.java\n *\n *  A mutable data type for an integer counter.\n *\n *  The test clients create n counters and performs trials increment\n *  operations on random counters.\n *\n * java Counter 6 600000\n *  100140 counter0\n *  100273 counter1\n *  99848 counter2\n *  100129 counter3\n *  99973 counter4\n *  99637 counter5\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Counter} class is a mutable data type to encapsulate a counter.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Counter implements Comparable<Counter> {\n\n    private final String name;     // counter name\n    private int count = 0;         // current value\n\n    /**\n     * Initializes a new counter starting at 0, with the given id.\n     *\n     * @param id the name of the counter\n     */\n    public Counter(String id) {\n        name = id;\n    }\n\n    /**\n     * Increments the counter by 1.\n     */\n    public void increment() {\n        count++;\n    }\n\n    /**\n     * Returns the current value of this counter.\n     *\n     * @return the current value of this counter\n     */\n    public int tally() {\n        return count;\n    }\n\n    /**\n     * Returns a string representation of this counter.\n     *\n     * @return a string representation of this counter\n     */\n    public String toString() {\n        return count + \" \" + name;\n    }\n\n    /**\n     * Compares this counter to the specified counter.\n     *\n     * @param  that the other counter\n     * @return {@code 0} if the value of this counter equals\n     *         the value of that counter; a negative integer if\n     *         the value of this counter is less than the value of\n     *         that counter; and a positive integer if the value\n     *         of this counter is greater than the value of that\n     *         counter\n     */\n    @Override\n    public int compareTo(Counter that) {\n        return Integer.compare(this.count, that.count);\n    }\n\n\n    /**\n     * Reads two command-line integers n and trials; creates n counters;\n     * increments trials counters at random; and prints results.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = Integer.parseInt(args[0]);\n        int trials = Integer.parseInt(args[1]);\n\n        // create n counters\n        Counter[] hits = new Counter[n];\n        for (int i = 0; i < n; i++) {\n            hits[i] = new Counter(\"counter\" + i);\n        }\n\n        // increment trials counters at random\n        for (int t = 0; t < trials; t++) {\n            hits[StdRandom.uniformInt(n)].increment();\n        }\n\n        // print results\n        for (int i = 0; i < n; i++) {\n            StdOut.println(hits[i]);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Cycle.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Cycle.java\n *  Execution:    java  Cycle filename.txt\n *  Dependencies: Graph.java Stack.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *                https://algs4.cs.princeton.edu/41graph/largeG.txt\n *\n *  Identifies a cycle.\n *  Runs in O(E + V) time.\n *\n *  % java Cycle tinyG.txt\n *  3 4 5 3\n *\n *  % java Cycle mediumG.txt\n *  15 0 225 15\n *\n *  % java Cycle largeG.txt\n *  996673 762 840164 4619 785187 194717 996673\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Cycle} class represents a data type for\n *  determining whether an undirected graph has a simple cycle.\n *  The <em>hasCycle</em> operation determines whether the graph has\n *  a cycle and, if so, the <em>cycle</em> operation returns one.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  (The depth-first search part takes only <em>O</em>(<em>V</em>) time;\n *  however, checking for self-loops and parallel edges takes\n *  &Theta;(<em>V</em> + <em>E</em>) time in the worst case.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Cycle {\n    private boolean[] marked;\n    private int[] edgeTo;\n    private Stack<Integer> cycle;\n\n    /**\n     * Determines whether the undirected graph {@code graph} has a cycle and,\n     * if so, finds such a cycle.\n     *\n     * @param graph the undirected graph\n     */\n    public Cycle(Graph graph) {\n        // need special case to identify parallel edge as a cycle\n        if (hasParallelEdges(graph)) return;\n\n        // don't need special case to identify self-loop as a cycle\n        // if (hasSelfLoop(graph)) return;\n\n        marked = new boolean[graph.V()];\n        edgeTo = new int[graph.V()];\n        for (int v = 0; v < graph.V(); v++)\n            if (!marked[v])\n                dfs(graph, -1, v);\n    }\n\n\n    // does this graph have a self loop?\n    // side effect: initialize cycle to be self loop\n    private boolean hasSelfLoop(Graph graph) {\n        for (int v = 0; v < graph.V(); v++) {\n            for (int w : graph.adj(v)) {\n                if (v == w) {\n                    cycle = new Stack<Integer>();\n                    cycle.push(v);\n                    cycle.push(v);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    // does this graph have two parallel edges?\n    // side effect: initialize cycle to be two parallel edges\n    private boolean hasParallelEdges(Graph graph) {\n        marked = new boolean[graph.V()];\n\n        for (int v = 0; v < graph.V(); v++) {\n\n            // check for parallel edges incident to v\n            for (int w : graph.adj(v)) {\n                if (marked[w]) {\n                    cycle = new Stack<Integer>();\n                    cycle.push(v);\n                    cycle.push(w);\n                    cycle.push(v);\n                    return true;\n                }\n                marked[w] = true;\n            }\n\n            // reset so marked[v] = false for all v\n            for (int w : graph.adj(v)) {\n                marked[w] = false;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Returns true if {@code graph} has a cycle.\n     *\n     * @return {@code true} if the graph has a cycle; {@code false} otherwise\n     */\n    public boolean hasCycle() {\n        return cycle != null;\n    }\n\n     /**\n     * Returns a cycle in the graph {@code G}.\n     * @return a cycle if the graph {@code G} has a cycle,\n     *         and {@code null} otherwise\n     */\n    public Iterable<Integer> cycle() {\n        return cycle;\n    }\n\n    private void dfs(Graph graph, int u, int v) {\n        marked[v] = true;\n        for (int w : graph.adj(v)) {\n\n            // short circuit if cycle already found\n            if (cycle != null) return;\n\n            if (!marked[w]) {\n                edgeTo[w] = v;\n                dfs(graph, v, w);\n            }\n\n            // check for cycle (but disregard reverse of edge leading to v)\n            else if (w != u) {\n                cycle = new Stack<Integer>();\n                for (int x = v; x != w; x = edgeTo[x]) {\n                    cycle.push(x);\n                }\n                cycle.push(w);\n                cycle.push(v);\n            }\n        }\n    }\n\n    /**\n     * Unit tests the {@code Cycle} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        Cycle finder = new Cycle(graph);\n        if (finder.hasCycle()) {\n            for (int v : finder.cycle()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n        else {\n            StdOut.println(\"Graph is acyclic\");\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Date.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Date.java\n *  Execution:    java Date\n *  Dependencies: StdOut.java\n *\n *  An immutable data type for dates.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Date} class is an immutable data type to encapsulate a\n *  date (day, month, and year).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Date implements Comparable<Date> {\n    private static final int[] DAYS = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n\n    private final int month;   // month (between 1 and 12)\n    private final int day;     // day   (between 1 and DAYS[month]\n    private final int year;    // year\n\n   /**\n     * Initializes a new date from the month, day, and year.\n     * @param month the month (between 1 and 12)\n     * @param day the day (between 1 and 28-31, depending on the month)\n     * @param year the year\n     * @throws IllegalArgumentException if this date is invalid\n     */\n    public Date(int month, int day, int year) {\n        if (!isValid(month, day, year)) throw new IllegalArgumentException(\"Invalid date\");\n        this.month = month;\n        this.day   = day;\n        this.year  = year;\n    }\n\n    /**\n     * Initializes new date specified as a string in form MM/DD/YYYY.\n     * @param date the string representation of this date\n     * @throws IllegalArgumentException if this date is invalid\n     */\n    public Date(String date) {\n        String[] fields = date.split(\"/\");\n        if (fields.length != 3) {\n            throw new IllegalArgumentException(\"Invalid date\");\n        }\n        month = Integer.parseInt(fields[0]);\n        day   = Integer.parseInt(fields[1]);\n        year  = Integer.parseInt(fields[2]);\n        if (!isValid(month, day, year)) throw new IllegalArgumentException(\"Invalid date\");\n    }\n\n    /**\n     * Return the month.\n     * @return the month (an integer between 1 and 12)\n     */\n    public int month() {\n        return month;\n    }\n\n    /**\n     * Returns the day.\n     * @return the day (an integer between 1 and 31)\n     */\n    public int day() {\n        return day;\n    }\n\n    /**\n     * Returns the year.\n     * @return the year\n     */\n    public int year() {\n        return year;\n    }\n\n\n    // is the given date valid?\n    private static boolean isValid(int m, int d, int y) {\n        if (m < 1 || m > 12)      return false;\n        if (d < 1 || d > DAYS[m]) return false;\n        if (m == 2 && d == 29 && !isLeapYear(y)) return false;\n        return true;\n    }\n\n    // is y a leap year?\n    private static boolean isLeapYear(int y) {\n        if (y % 400 == 0) return true;\n        if (y % 100 == 0) return false;\n        return y % 4 == 0;\n    }\n\n    /**\n     * Returns the next date in the calendar.\n     *\n     * @return a date that represents the next day after this day\n     */\n    public Date next() {\n        if (isValid(month, day + 1, year))    return new Date(month, day + 1, year);\n        else if (isValid(month + 1, 1, year)) return new Date(month + 1, 1, year);\n        else                                  return new Date(1, 1, year + 1);\n    }\n\n    /**\n     * Compares two dates chronologically.\n     *\n     * @param  that the other date\n     * @return {@code true} if this date is after that date; {@code false} otherwise\n     */\n    public boolean isAfter(Date that) {\n        return compareTo(that) > 0;\n    }\n\n    /**\n     * Compares two dates chronologically.\n     *\n     * @param  that the other date\n     * @return {@code true} if this date is before that date; {@code false} otherwise\n     */\n    public boolean isBefore(Date that) {\n        return compareTo(that) < 0;\n    }\n\n    /**\n     * Compares two dates chronologically.\n     *\n     * @return the value {@code 0} if the argument date is equal to this date;\n     *         a negative integer if this date is chronologically less than\n     *         the argument date; and a positive integer if this date is\n     *         chronologically after the argument date\n     */\n    @Override\n    public int compareTo(Date that) {\n        if (this.year  < that.year)  return -1;\n        if (this.year  > that.year)  return +1;\n        if (this.month < that.month) return -1;\n        if (this.month > that.month) return +1;\n        if (this.day   < that.day)   return -1;\n        if (this.day   > that.day)   return +1;\n        return 0;\n    }\n\n    /**\n     * Returns a string representation of this date.\n     *\n     * @return the string representation in the format MM/DD/YYYY\n     */\n    @Override\n    public String toString() {\n        return month + \"/\" + day + \"/\" + year;\n    }\n\n    /**\n     * Compares this date to the specified date.\n     *\n     * @param  other the other date\n     * @return {@code true} if this date equals {@code other}; {@code false} otherwise\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Date that = (Date) other;\n        return (this.month == that.month) && (this.day == that.day) && (this.year == that.year);\n    }\n\n    /**\n     * Returns an integer hash code for this date.\n     *\n     * @return an integer hash code for this date\n     */\n    @Override\n    public int hashCode() {\n        return day + 31*month + 31*12*year;\n    }\n\n    /**\n     * Unit tests the {@code Date} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Date today = new Date(2, 25, 2004);\n        StdOut.println(today);\n        for (int i = 0; i < 10; i++) {\n            today = today.next();\n            StdOut.println(today);\n        }\n\n        StdOut.println(today.isAfter(today.next()));\n        StdOut.println(today.isAfter(today));\n        StdOut.println(today.next().isAfter(today));\n\n\n        Date birthday = new Date(10, 16, 1971);\n        StdOut.println(birthday);\n        for (int i = 0; i < 10; i++) {\n            birthday = birthday.next();\n            StdOut.println(birthday);\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DeDup.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DeDup.java\n *  Execution:    java DeDup < input.txt\n *  Dependencies: SET StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/tinyTale.txt\n *\n *  Read in a list of words from standard input and print out\n *  each word, removing any duplicates.\n *\n *  % more tinyTale.txt\n *  it was the best of times it was the worst of times\n *  it was the age of wisdom it was the age of foolishness\n *  it was the epoch of belief it was the epoch of incredulity\n *  it was the season of light it was the season of darkness\n *  it was the spring of hope it was the winter of despair\n *\n *  % java DeDup < tinyTale.txt\n *  it\n *  was\n *  the\n *  best\n *  of\n *  times\n *  worst\n *  age\n *  wisdom\n *  ...\n *  winter\n *  despair\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DeDup} class provides a client for reading in a sequence of\n *  words from standard input and printing each word, removing any duplicates.\n *  It is useful as a test client for various symbol table implementations.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DeDup {\n\n    // Do not instantiate.\n    private DeDup() { }\n\n    public static void main(String[] args) {\n        SET<String> set = new SET<String>();\n\n        // read in strings and add to set\n        while (!StdIn.isEmpty()) {\n            String key = StdIn.readString();\n            if (!set.contains(key)) {\n                set.add(key);\n                StdOut.println(key);\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DegreesOfSeparation.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DegreesOfSeparation.java\n *  Execution:    java DegreesOfSeparation filename delimiter source\n *  Dependencies: SymbolGraph.java Graph.java BreadthFirstPaths.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/routes.txt\n *                https://algs4.cs.princeton.edu/41graph/movies.txt\n *\n *\n *  %  java DegreesOfSeparation routes.txt \" \" \"JFK\"\n *  LAS\n *     JFK\n *     ORD\n *     DEN\n *     LAS\n *  DFW\n *     JFK\n *     ORD\n *     DFW\n *  EWR\n *     Not in database.\n *\n *  % java DegreesOfSeparation movies.txt \"/\" \"Bacon, Kevin\"\n *  Kidman, Nicole\n *     Bacon, Kevin\n *     Woodsman, The (2004)\n *     Grier, David Alan\n *     Bewitched (2005)\n *     Kidman, Nicole\n *  Grant, Cary\n *     Bacon, Kevin\n *     Planes, Trains & Automobiles (1987)\n *     Martin, Steve (I)\n *     Dead Men Don't Wear Plaid (1982)\n *     Grant, Cary\n *\n *  % java DegreesOfSeparation movies.txt \"/\" \"Animal House (1978)\"\n *  Titanic (1997)\n *     Animal House (1978)\n *     Allen, Karen (I)\n *     Raiders of the Lost Ark (1981)\n *     Taylor, Rocky (I)\n *     Titanic (1997)\n *  To Catch a Thief (1955)\n *     Animal House (1978)\n *     Vernon, John (I)\n *     Topaz (1969)\n *     Hitchcock, Alfred (I)\n *     To Catch a Thief (1955)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DegreesOfSeparation} class provides a client for finding\n *  the degree of separation between one distinguished individual and\n *  every other individual in a social network.\n *  As an example, if the social network consists of actors in which\n *  two actors are connected by a link if they appeared in the same movie,\n *  and Kevin Bacon is the distinguished individual, then the client\n *  computes the Kevin Bacon number of every actor in the network.\n *  <p>\n *  The running time is proportional to the number of individuals and\n *  connections in the network. If the connections are given implicitly,\n *  as in the movie network example (where every two actors are connected\n *  if they appear in the same movie), the efficiency of the algorithm\n *  is improved by allowing both movie and actor vertices and connecting\n *  each movie to all of the actors that appear in that movie.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DegreesOfSeparation {\n\n    // this class cannot be instantiated\n    private DegreesOfSeparation() { }\n\n    /**\n     *  Reads in a social network from a file, and then repeatedly reads in\n     *  individuals from standard input and prints out their degrees of\n     *  separation.\n     *  Takes three command-line arguments: the name of a file,\n     *  a delimiter, and the name of the distinguished individual.\n     *  Each line in the file contains the name of a vertex, followed by a\n     *  list of the names of the vertices adjacent to that vertex,\n     *  separated by the delimiter.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String filename  = args[0];\n        String delimiter = args[1];\n        String source    = args[2];\n\n        // StdOut.println(\"Source: \" + source);\n\n        SymbolGraph sg = new SymbolGraph(filename, delimiter);\n        Graph graph = sg.graph();\n        if (!sg.contains(source)) {\n            StdOut.println(source + \" not in database.\");\n            return;\n        }\n\n        int s = sg.indexOf(source);\n        BreadthFirstPaths bfs = new BreadthFirstPaths(graph, s);\n\n        while (!StdIn.isEmpty()) {\n            String sink = StdIn.readLine();\n            if (sg.contains(sink)) {\n                int t = sg.indexOf(sink);\n                if (bfs.hasPathTo(t)) {\n                    for (int v : bfs.pathTo(t)) {\n                        StdOut.println(\"   \" + sg.nameOf(v));\n                    }\n                }\n                else {\n                    StdOut.println(\"Not connected\");\n                }\n            }\n            else {\n                StdOut.println(\"   Not in database.\");\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DepthFirstDirectedPaths.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DepthFirstDirectedPaths.java\n *  Execution:    java DepthFirstDirectedPaths digraph.txt s\n *  Dependencies: Digraph.java Stack.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Determine reachability in a digraph from a given vertex using\n *  depth-first search.\n *  Runs in O(E + V) time.\n *\n *  % java DepthFirstDirectedPaths tinyDG.txt 3\n *  3 to 0:  3-5-4-2-0\n *  3 to 1:  3-5-4-2-0-1\n *  3 to 2:  3-5-4-2\n *  3 to 3:  3\n *  3 to 4:  3-5-4\n *  3 to 5:  3-5\n *  3 to 6:  not connected\n *  3 to 7:  not connected\n *  3 to 8:  not connected\n *  3 to 9:  not connected\n *  3 to 10:  not connected\n *  3 to 11:  not connected\n *  3 to 12:  not connected\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DepthFirstDirectedPaths} class represents a data type for\n *  finding directed paths from a source vertex <em>s</em> to every\n *  other vertex in the digraph.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DepthFirstDirectedPaths {\n    private boolean[] marked;  // marked[v] = true iff v is reachable from s\n    private int[] edgeTo;      // edgeTo[v] = last edge on path from s to v\n    private final int s;       // source vertex\n\n    /**\n     * Computes a directed path from {@code s} to every other vertex in {@code digraph}.\n     * @param  digraph the digraph\n     * @param  s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DepthFirstDirectedPaths(Digraph digraph, int s) {\n        marked = new boolean[digraph.V()];\n        edgeTo = new int[digraph.V()];\n        this.s = s;\n        validateVertex(s);\n        dfs(digraph, s);\n    }\n\n    private void dfs(Digraph digraph, int v) {\n        marked[v] = true;\n        for (int w : digraph.adj(v)) {\n            if (!marked[w]) {\n                edgeTo[w] = v;\n                dfs(digraph, w);\n            }\n        }\n    }\n\n    /**\n     * Is there a directed path from the source vertex {@code s} to vertex {@code v}?\n     * @param  v the vertex\n     * @return {@code true} if there is a directed path from the source\n     *         vertex {@code s} to vertex {@code v}, {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n\n    /**\n     * Returns a directed path from the source vertex {@code s} to vertex {@code v}, or\n     * {@code null} if no such path.\n     * @param  v the vertex\n     * @return the sequence of vertices on a directed path from the source vertex\n     *         {@code s} to vertex {@code v}, as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Integer> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<Integer> path = new Stack<Integer>();\n        for (int x = v; x != s; x = edgeTo[x])\n            path.push(x);\n        path.push(s);\n        return path;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code DepthFirstDirectedPaths} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n        // StdOut.println(digraph);\n\n        int s = Integer.parseInt(args[1]);\n        DepthFirstDirectedPaths dfs = new DepthFirstDirectedPaths(digraph, s);\n\n        for (int v = 0; v < digraph.V(); v++) {\n            if (dfs.hasPathTo(v)) {\n                StdOut.printf(\"%d to %d:  \", s, v);\n                for (int x : dfs.pathTo(v)) {\n                    if (x == s) StdOut.print(x);\n                    else        StdOut.print(\"-\" + x);\n                }\n                StdOut.println();\n            }\n\n            else {\n                StdOut.printf(\"%d to %d:  not connected\\n\", s, v);\n            }\n\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DepthFirstOrder.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DepthFirstOrder.java\n *  Execution:    java DepthFirstOrder digraph.txt\n *  Dependencies: Digraph.java Queue.java Stack.java StdOut.java\n *                EdgeWeightedDigraph.java DirectedEdge.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt\n *                https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *\n *  Compute preorder and postorder for a digraph or edge-weighted digraph.\n *  Runs in O(E + V) time.\n *\n *  % java DepthFirstOrder tinyDAG.txt\n *     v  pre post\n *  --------------\n *     0    0    8\n *     1    3    2\n *     2    9   10\n *     3   10    9\n *     4    2    0\n *     5    1    1\n *     6    4    7\n *     7   11   11\n *     8   12   12\n *     9    5    6\n *    10    8    5\n *    11    6    4\n *    12    7    3\n *  Preorder:  0 5 4 1 6 9 11 12 10 2 3 7 8\n *  Postorder: 4 5 1 12 11 10 9 6 0 3 2 7 8\n *  Reverse postorder: 8 7 2 3 0 6 9 10 11 12 1 5 4\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DepthFirstOrder} class represents a data type for\n *  determining depth-first search ordering of the vertices in a digraph\n *  or edge-weighted digraph, including preorder, postorder, and reverse postorder.\n *  <p>\n *  This implementation uses depth-first search.\n *  Each constructor takes &Theta;(<em>V</em> + <em>E</em>) time,\n *  where <em>V</em> is the number of vertices and <em>E</em> is the\n *  number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DepthFirstOrder {\n    private boolean[] marked;          // marked[v] = has v been marked in dfs?\n    private int[] pre;                 // pre[v]    = preorder  number of v\n    private int[] post;                // post[v]   = postorder number of v\n    private Queue<Integer> preorder;   // vertices in preorder\n    private Queue<Integer> postorder;  // vertices in postorder\n    private int preCounter;            // counter or preorder numbering\n    private int postCounter;           // counter for postorder numbering\n\n    /**\n     * Determines a depth-first order for a digraph.\n     * @param digraph the digraph\n     */\n    public DepthFirstOrder(Digraph digraph) {\n        pre    = new int[digraph.V()];\n        post   = new int[digraph.V()];\n        postorder = new Queue<Integer>();\n        preorder  = new Queue<Integer>();\n        marked    = new boolean[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            if (!marked[v]) dfs(digraph, v);\n\n        assert check();\n    }\n\n    /**\n     * Determines a depth-first order for an edge-weighted digraph.\n     * @param digraph the edge-weighted digraph\n     */\n    public DepthFirstOrder(EdgeWeightedDigraph digraph) {\n        pre    = new int[digraph.V()];\n        post   = new int[digraph.V()];\n        postorder = new Queue<Integer>();\n        preorder  = new Queue<Integer>();\n        marked    = new boolean[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            if (!marked[v]) dfs(digraph, v);\n    }\n\n    // run DFS in the digraph from vertex v and compute preorder/postorder\n    private void dfs(Digraph digraph, int v) {\n        marked[v] = true;\n        pre[v] = preCounter++;\n        preorder.enqueue(v);\n        for (int w : digraph.adj(v)) {\n            if (!marked[w]) {\n                dfs(digraph, w);\n            }\n        }\n        postorder.enqueue(v);\n        post[v] = postCounter++;\n    }\n\n    // run DFS in an edge-weighted digraph from vertex v and compute preorder/postorder\n    private void dfs(EdgeWeightedDigraph digraph, int v) {\n        marked[v] = true;\n        pre[v] = preCounter++;\n        preorder.enqueue(v);\n        for (DirectedEdge e : digraph.adj(v)) {\n            int w = e.to();\n            if (!marked[w]) {\n                dfs(digraph, w);\n            }\n        }\n        postorder.enqueue(v);\n        post[v] = postCounter++;\n    }\n\n    /**\n     * Returns the preorder number of vertex {@code v}.\n     * @param  v the vertex\n     * @return the preorder number of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int pre(int v) {\n        validateVertex(v);\n        return pre[v];\n    }\n\n    /**\n     * Returns the postorder number of vertex {@code v}.\n     * @param  v the vertex\n     * @return the postorder number of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int post(int v) {\n        validateVertex(v);\n        return post[v];\n    }\n\n    /**\n     * Returns the vertices in postorder.\n     * @return the vertices in postorder, as an iterable of vertices\n     */\n    public Iterable<Integer> post() {\n        return postorder;\n    }\n\n    /**\n     * Returns the vertices in preorder.\n     * @return the vertices in preorder, as an iterable of vertices\n     */\n    public Iterable<Integer> pre() {\n        return preorder;\n    }\n\n    /**\n     * Returns the vertices in reverse postorder.\n     * @return the vertices in reverse postorder, as an iterable of vertices\n     */\n    public Iterable<Integer> reversePost() {\n        Stack<Integer> reverse = new Stack<Integer>();\n        for (int v : postorder)\n            reverse.push(v);\n        return reverse;\n    }\n\n\n    // check that pre() and post() are consistent with pre(v) and post(v)\n    private boolean check() {\n\n        // check that post(v) is consistent with post()\n        int r = 0;\n        for (int v : post()) {\n            if (post(v) != r) {\n                StdOut.println(\"post(v) and post() inconsistent\");\n                return false;\n            }\n            r++;\n        }\n\n        // check that pre(v) is consistent with pre()\n        r = 0;\n        for (int v : pre()) {\n            if (pre(v) != r) {\n                StdOut.println(\"pre(v) and pre() inconsistent\");\n                return false;\n            }\n            r++;\n        }\n\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code DepthFirstOrder} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n\n        DepthFirstOrder dfs = new DepthFirstOrder(digraph);\n        StdOut.println(\"   v  pre post\");\n        StdOut.println(\"--------------\");\n        for (int v = 0; v < digraph.V(); v++) {\n            StdOut.printf(\"%4d %4d %4d\\n\", v, dfs.pre(v), dfs.post(v));\n        }\n\n        StdOut.print(\"Preorder:  \");\n        for (int v : dfs.pre()) {\n            StdOut.print(v + \" \");\n        }\n        StdOut.println();\n\n        StdOut.print(\"Postorder: \");\n        for (int v : dfs.post()) {\n            StdOut.print(v + \" \");\n        }\n        StdOut.println();\n\n        StdOut.print(\"Reverse postorder: \");\n        for (int v : dfs.reversePost()) {\n            StdOut.print(v + \" \");\n        }\n        StdOut.println();\n\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DepthFirstPaths.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DepthFirstPaths.java\n *  Execution:    java DepthFirstPaths G s\n *  Dependencies: Graph.java Stack.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyCG.txt\n *                https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *                https://algs4.cs.princeton.edu/41graph/largeG.txt\n *\n *  Run depth-first search on an undirected graph.\n *\n *  %  java Graph tinyCG.txt\n *  6 8\n *  0: 2 1 5\n *  1: 0 2\n *  2: 0 1 3 4\n *  3: 5 4 2\n *  4: 3 2\n *  5: 3 0\n *\n *  % java DepthFirstPaths tinyCG.txt 0\n *  0 to 0:  0\n *  0 to 1:  0-2-1\n *  0 to 2:  0-2\n *  0 to 3:  0-2-3\n *  0 to 4:  0-2-3-4\n *  0 to 5:  0-2-3-5\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DepthFirstPaths} class represents a data type for finding\n *  paths from a source vertex <em>s</em> to every other vertex\n *  in an undirected graph.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DepthFirstPaths {\n    private boolean[] marked;    // marked[v] = is there an s-v path?\n    private int[] edgeTo;        // edgeTo[v] = last edge on s-v path\n    private final int s;         // source vertex\n\n    /**\n     * Computes a path between {@code s} and every other vertex in {@code graph}.\n     * @param graph the graph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DepthFirstPaths(Graph graph, int s) {\n        this.s = s;\n        edgeTo = new int[graph.V()];\n        marked = new boolean[graph.V()];\n        validateVertex(s);\n        dfs(graph, s);\n    }\n\n    // depth first search from v\n    private void dfs(Graph graph, int v) {\n        marked[v] = true;\n        for (int w : graph.adj(v)) {\n            if (!marked[w]) {\n                edgeTo[w] = v;\n                dfs(graph, w);\n            }\n        }\n    }\n\n    /**\n     * Is there a path between the source vertex {@code s} and vertex {@code v}?\n     * @param v the vertex\n     * @return {@code true} if there is a path, {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    /**\n     * Returns a path between the source vertex {@code s} and vertex {@code v}, or\n     * {@code null} if no such path.\n     * @param  v the vertex\n     * @return the sequence of vertices on a path between the source vertex\n     *         {@code s} and vertex {@code v}, as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Integer> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<Integer> path = new Stack<Integer>();\n        for (int x = v; x != s; x = edgeTo[x])\n            path.push(x);\n        path.push(s);\n        return path;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code DepthFirstPaths} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        int s = Integer.parseInt(args[1]);\n        DepthFirstPaths dfs = new DepthFirstPaths(graph, s);\n\n        for (int v = 0; v < graph.V(); v++) {\n            if (dfs.hasPathTo(v)) {\n                StdOut.printf(\"%d to %d:  \", s, v);\n                for (int x : dfs.pathTo(v)) {\n                    if (x == s) StdOut.print(x);\n                    else        StdOut.print(\"-\" + x);\n                }\n                StdOut.println();\n            }\n\n            else {\n                StdOut.printf(\"%d to %d:  not connected\\n\", s, v);\n            }\n\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DepthFirstSearch.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DepthFirstSearch.java\n *  Execution:    java DepthFirstSearch filename.txt s\n *  Dependencies: Graph.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *\n *  Run depth first search on an undirected graph.\n *  Runs in O(E + V) time.\n *\n *  % java DepthFirstSearch tinyG.txt 0\n *  0 1 2 3 4 5 6\n *  NOT connected\n *\n *  % java DepthFirstSearch tinyG.txt 9\n *  9 10 11 12\n *  NOT connected\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DepthFirstSearch} class represents a data type for\n *  determining the vertices connected to a given source vertex <em>s</em>\n *  in an undirected graph. For versions that find the paths, see\n *  {@link DepthFirstPaths} and {@link BreadthFirstPaths}.\n *  <p>\n *  This implementation uses depth-first search.\n *  See {@link NonrecursiveDFS} for a non-recursive version.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the worst\n *  case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DepthFirstSearch {\n    private boolean[] marked;    // marked[v] = is there an s-v path?\n    private int count;           // number of vertices connected to s\n\n    /**\n     * Computes the vertices in {@code graph} that are\n     * connected to the source vertex {@code s}.\n     * @param graph the graph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DepthFirstSearch(Graph graph, int s) {\n        marked = new boolean[graph.V()];\n        validateVertex(s);\n        dfs(graph, s);\n    }\n\n    // depth first search from v\n    private void dfs(Graph graph, int v) {\n        count++;\n        marked[v] = true;\n        for (int w : graph.adj(v)) {\n            if (!marked[w]) {\n                dfs(graph, w);\n            }\n        }\n    }\n\n    /**\n     * Is there a path between the source vertex {@code s} and vertex {@code v}?\n     * @param v the vertex\n     * @return {@code true} if there is a path, {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean marked(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    /**\n     * Returns the number of vertices connected to the source vertex {@code s}.\n     * @return the number of vertices connected to the source vertex {@code s}\n     */\n    public int count() {\n        return count;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code DepthFirstSearch} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        int s = Integer.parseInt(args[1]);\n        DepthFirstSearch search = new DepthFirstSearch(graph, s);\n        for (int v = 0; v < graph.V(); v++) {\n            if (search.marked(v))\n                StdOut.print(v + \" \");\n        }\n\n        StdOut.println();\n        if (search.count() != graph.V()) StdOut.println(\"NOT connected\");\n        else                             StdOut.println(\"connected\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Digraph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Digraph.java\n *  Execution:    java Digraph filename.txt\n *  Dependencies: Bag.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  A graph, implemented using an array of lists.\n *  Parallel edges and self-loops are permitted.\n *\n *  % java Digraph tinyDG.txt\n *  13 vertices, 22 edges\n *  0: 5 1\n *  1:\n *  2: 0 3\n *  3: 5 2\n *  4: 3 2\n *  5: 4\n *  6: 9 4 8 0\n *  7: 6 9\n *  8: 6\n *  9: 11 10\n *  10: 12\n *  11: 4 12\n *  12: 9\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code Digraph} class represents a directed graph of vertices\n *  named 0 through <em>V</em> - 1.\n *  It supports the following two primary operations: add an edge to the digraph,\n *  iterate over all of the vertices adjacent from a given vertex.\n *  It also provides\n *  methods for returning the indegree or outdegree of a vertex,\n *  the number of vertices <em>V</em> in the digraph,\n *  the number of edges <em>E</em> in the digraph, and the reverse digraph.\n *  Parallel edges and self-loops are permitted.\n *  <p>\n *  This implementation uses an <em>adjacency-lists representation</em>, which\n *  is a vertex-indexed array of {@link Bag} objects.\n *  It uses &Theta;(<em>E</em> + <em>V</em>) space, where <em>E</em> is\n *  the number of edges and <em>V</em> is the number of vertices.\n *  The <code>reverse()</code> method takes &Theta;(<em>E</em> + <em>V</em>) time\n *  and space; all other instance methods take &Theta;(1) time. (Though, iterating over\n *  the vertices returned by {@link #adj(int)} takes time proportional\n *  to the outdegree of the vertex.)\n *  Constructing an empty digraph with <em>V</em> vertices takes\n *  &Theta;(<em>V</em>) time; constructing a digraph with <em>E</em> edges\n *  and <em>V</em> vertices takes &Theta;(<em>E</em> + <em>V</em>) time.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class Digraph {\n    private static final String NEWLINE = System.getProperty(\"line.separator\");\n\n    private final int V;           // number of vertices in this digraph\n    private int E;                 // number of edges in this digraph\n    private Bag<Integer>[] adj;    // adj[v] = adjacency list for vertex v\n    private int[] indegree;        // indegree[v] = indegree of vertex v\n\n    /**\n     * Initializes an empty digraph with <em>V</em> vertices.\n     *\n     * @param  V the number of vertices\n     * @throws IllegalArgumentException if {@code V < 0}\n     */\n    public Digraph(int V) {\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices in a Digraph must be non-negative\");\n        this.V = V;\n        this.E = 0;\n        indegree = new int[V];\n        adj = (Bag<Integer>[]) new Bag[V];\n        for (int v = 0; v < V; v++) {\n            adj[v] = new Bag<Integer>();\n        }\n    }\n\n    /**\n     * Initializes a digraph from the specified input stream.\n     * The format is the number of vertices <em>V</em>,\n     * followed by the number of edges <em>E</em>,\n     * followed by <em>E</em> pairs of vertices, with each entry separated by whitespace.\n     *\n     * @param  in the input stream\n     * @throws IllegalArgumentException if {@code in} is {@code null}\n     * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range\n     * @throws IllegalArgumentException if the number of vertices or edges is negative\n     * @throws IllegalArgumentException if the input stream is in the wrong format\n     */\n    public Digraph(In in) {\n        if (in == null) throw new IllegalArgumentException(\"argument is null\");\n        try {\n            this.V = in.readInt();\n            if (V < 0) throw new IllegalArgumentException(\"number of vertices in a Digraph must be non-negative\");\n            indegree = new int[V];\n            adj = (Bag<Integer>[]) new Bag[V];\n            for (int v = 0; v < V; v++) {\n                adj[v] = new Bag<Integer>();\n            }\n            int E = in.readInt();\n            if (E < 0) throw new IllegalArgumentException(\"number of edges in a Digraph must be non-negative\");\n            for (int i = 0; i < E; i++) {\n                int v = in.readInt();\n                int w = in.readInt();\n                addEdge(v, w);\n            }\n        }\n        catch (NoSuchElementException e) {\n            throw new IllegalArgumentException(\"invalid input format in Digraph constructor\", e);\n        }\n    }\n\n    /**\n     * Initializes a new digraph that is a deep copy of the specified digraph.\n     *\n     * @param  digraph the digraph to copy\n     * @throws IllegalArgumentException if {@code digraph} is {@code null}\n     */\n    public Digraph(Digraph digraph) {\n        if (digraph == null) throw new IllegalArgumentException(\"argument is null\");\n\n        this.V = digraph.V();\n        this.E = digraph.E();\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices in a Digraph must be non-negative\");\n\n        // update indegrees\n        indegree = new int[V];\n        for (int v = 0; v < V; v++)\n            this.indegree[v] = digraph.indegree(v);\n\n        // update adjacency lists\n        adj = (Bag<Integer>[]) new Bag[V];\n        for (int v = 0; v < V; v++) {\n            adj[v] = new Bag<Integer>();\n        }\n\n        for (int v = 0; v < digraph.V(); v++) {\n            // reverse so that adjacency list is in same order as original\n            Stack<Integer> reverse = new Stack<Integer>();\n            for (int w : digraph.adj[v]) {\n                reverse.push(w);\n            }\n            for (int w : reverse) {\n                adj[v].add(w);\n            }\n        }\n    }\n\n    /**\n     * Returns the number of vertices in this digraph.\n     *\n     * @return the number of vertices in this digraph\n     */\n    public int V() {\n        return V;\n    }\n\n    /**\n     * Returns the number of edges in this digraph.\n     *\n     * @return the number of edges in this digraph\n     */\n    public int E() {\n        return E;\n    }\n\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Adds the directed edge v→w to this digraph.\n     *\n     * @param  v the tail vertex\n     * @param  w the head vertex\n     * @throws IllegalArgumentException unless both {@code 0 <= v < V} and {@code 0 <= w < V}\n     */\n    public void addEdge(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        adj[v].add(w);\n        indegree[w]++;\n        E++;\n    }\n\n    /**\n     * Returns the vertices adjacent from vertex {@code v} in this digraph.\n     *\n     * @param  v the vertex\n     * @return the vertices adjacent from vertex {@code v} in this digraph, as an iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Integer> adj(int v) {\n        validateVertex(v);\n        return adj[v];\n    }\n\n    /**\n     * Returns the number of directed edges incident from vertex {@code v}.\n     * This is known as the <em>outdegree</em> of vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the outdegree of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int outdegree(int v) {\n        validateVertex(v);\n        return adj[v].size();\n    }\n\n    /**\n     * Returns the number of directed edges incident to vertex {@code v}.\n     * This is known as the <em>indegree</em> of vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the indegree of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int indegree(int v) {\n        validateVertex(v);\n        return indegree[v];\n    }\n\n    /**\n     * Returns the reverse of the digraph.\n     *\n     * @return the reverse of the digraph\n     */\n    public Digraph reverse() {\n        Digraph reverse = new Digraph(V);\n        for (int v = 0; v < V; v++) {\n            for (int w : adj(v)) {\n                reverse.addEdge(w, v);\n            }\n        }\n        return reverse;\n    }\n\n    /**\n     * Returns a string representation of the graph.\n     *\n     * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,\n     *         followed by the <em>V</em> adjacency lists\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(V + \" vertices, \" + E + \" edges \" + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            s.append(String.format(\"%d: \", v));\n            for (int w : adj[v]) {\n                s.append(String.format(\"%d \", w));\n            }\n            s.append(NEWLINE);\n        }\n        return s.toString();\n    }\n\n    /**\n     * Returns a string representation of this digraph in DOT format,\n     * suitable for visualization with Graphviz.\n     *\n     * To visualize the digraph, install Graphviz (e.g., \"brew install graphviz\").\n     * Then use one of the graph visualization tools\n     *    - dot    (hierarchical or layer drawing)\n     *    - neato  (spring model)\n     *    - fdp    (force-directed placement)\n     *    - sfdp   (scalable force-directed placement)\n     *    - twopi  (radial layout)\n     *\n     * For example, the following commands will create graph drawings in SVG\n     * and PDF formats\n     *    - dot input.dot -Tsvg -o output.svg\n     *    - dot input.dot -Tpdf -o output.pdf\n     *\n     * To change the digraph attributes (e.g., vertex and edge shapes, arrows, colors)\n     *  in the DOT format, see https://graphviz.org/doc/info/lang.html\n     *\n     * @return a string representation of this digraph in DOT format\n     */\n    public String toDot() {\n        StringBuilder s = new StringBuilder();\n        s.append(\"digraph {\" + NEWLINE);\n        s.append(\"node[shape=circle, style=filled, fixedsize=true, width=0.3, fontsize=\\\"10pt\\\"]\" + NEWLINE);\n        s.append(\"edge[arrowhead=normal]\" + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            for (int w : adj[v]) {\n                s.append(v + \" -> \" + w + NEWLINE);\n            }\n        }\n        s.append(\"}\" + NEWLINE);\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code Digraph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph graph = new Digraph(in);\n        StdOut.println(graph);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DigraphGenerator.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DigraphGenerator.java\n *  Execution:    java DigraphGenerator V E\n *  Dependencies: Digraph.java\n *\n *  A digraph generator.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DigraphGenerator} class provides static methods for creating\n *  various digraphs, including Erdos-Renyi random digraphs, random DAGs,\n *  random rooted trees, random rooted DAGs, random tournaments, path digraphs,\n *  cycle digraphs, and the complete digraph.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DigraphGenerator {\n    private static final class Edge implements Comparable<Edge> {\n        private final int v;\n        private final int w;\n\n        private Edge(int v, int w) {\n            this.v = v;\n            this.w = w;\n        }\n\n        public int compareTo(Edge that) {\n            if (this.v < that.v) return -1;\n            if (this.v > that.v) return +1;\n            if (this.w < that.w) return -1;\n            if (this.w > that.w) return +1;\n            return 0;\n        }\n    }\n\n    // this class cannot be instantiated\n    private DigraphGenerator() { }\n\n    /**\n     * Returns a random simple digraph containing {@code V} vertices and {@code E} edges.\n     * @param V the number of vertices\n     * @param E the number of vertices\n     * @return a random simple digraph on {@code V} vertices, containing a total\n     *     of {@code E} edges\n     * @throws IllegalArgumentException if no such simple digraph exists\n     */\n    public static Digraph simple(int V, int E) {\n        if (E > (long) V*(V-1)) throw new IllegalArgumentException(\"Too many edges\");\n        if (E < 0)              throw new IllegalArgumentException(\"Too few edges\");\n        Digraph digraph = new Digraph(V);\n        SET<Edge> set = new SET<Edge>();\n        while (digraph.E() < E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            Edge e = new Edge(v, w);\n            if ((v != w) && !set.contains(e)) {\n                set.add(e);\n                digraph.addEdge(v, w);\n            }\n        }\n        return digraph;\n    }\n\n   /**\n     * Returns a random simple digraph on {@code V} vertices, with an\n     * edge between any two vertices with probability {@code p}. This is sometimes\n     * referred to as the Erdos-Renyi random digraph model.\n     * This implementations takes time proportional to V^2 (even if {@code p} is small).\n     * @param V the number of vertices\n     * @param p the probability of choosing an edge\n     * @return a random simple digraph on {@code V} vertices, with an edge between\n     *     any two vertices with probability {@code p}\n     * @throws IllegalArgumentException if probability is not between 0 and 1\n     */\n    public static Digraph simple(int V, double p) {\n        if (p < 0.0 || p > 1.0)\n            throw new IllegalArgumentException(\"Probability must be between 0 and 1\");\n        Digraph digraph = new Digraph(V);\n        for (int v = 0; v < V; v++)\n            for (int w = 0; w < V; w++)\n                if (v != w)\n                    if (StdRandom.bernoulli(p))\n                        digraph.addEdge(v, w);\n        return digraph;\n    }\n\n    /**\n     * Returns the complete digraph on {@code V} vertices.\n     * In a complete digraph, every pair of distinct vertices is connected\n     * by two antiparallel edges. There are {@code V*(V-1)} edges.\n     * @param V the number of vertices\n     * @return the complete digraph on {@code V} vertices\n     */\n    public static Digraph complete(int V) {\n        Digraph digraph = new Digraph(V);\n        for (int v = 0; v < V; v++)\n            for (int w = 0; w < V; w++)\n                    if (v != w) digraph.addEdge(v, w);\n        return digraph;\n    }\n\n    /**\n     * Returns a random simple DAG containing {@code V} vertices and {@code E} edges.\n     * Note: it is not uniformly selected at random among all such DAGs.\n     * @param V the number of vertices\n     * @param E the number of vertices\n     * @return a random simple DAG on {@code V} vertices, containing a total\n     *     of {@code E} edges\n     * @throws IllegalArgumentException if no such simple DAG exists\n     */\n    public static Digraph dag(int V, int E) {\n        if (E > (long) V*(V-1) / 2) throw new IllegalArgumentException(\"Too many edges\");\n        if (E < 0)                  throw new IllegalArgumentException(\"Too few edges\");\n        Digraph digraph = new Digraph(V);\n        SET<Edge> set = new SET<Edge>();\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        while (digraph.E() < E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            Edge e = new Edge(v, w);\n            if ((v < w) && !set.contains(e)) {\n                set.add(e);\n                digraph.addEdge(vertices[v], vertices[w]);\n            }\n        }\n        return digraph;\n    }\n\n    /**\n     * Returns a random tournament digraph on {@code V} vertices. A tournament digraph\n     * is a digraph in which, for every pair of vertices, there is one and only one\n     * directed edge connecting them. A tournament is an oriented complete graph.\n     * @param V the number of vertices\n     * @return a random tournament digraph on {@code V} vertices\n     */\n    public static Digraph tournament(int V) {\n        Digraph digraph = new Digraph(V);\n        for (int v = 0; v < digraph.V(); v++) {\n            for (int w = v+1; w < digraph.V(); w++) {\n                if (StdRandom.bernoulli(0.5)) digraph.addEdge(v, w);\n                else                          digraph.addEdge(w, v);\n            }\n        }\n        return digraph;\n    }\n\n    /**\n     * Returns a complete rooted-in DAG on {@code V} vertices.\n     * A rooted in-tree is a DAG in which there is a single vertex\n     * reachable from every other vertex. A complete rooted in-DAG\n     * has V*(V-1)/2 edges.\n     * @param V the number of vertices\n     * @return a complete rooted-in DAG on {@code V} vertices\n     */\n    public static Digraph completeRootedInDAG(int V) {\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V; i++)\n            for (int j = i+1; j < V; j++)\n                 digraph.addEdge(vertices[i], vertices[j]);\n\n        return digraph;\n    }\n\n    /**\n     * Returns a random rooted-in DAG on {@code V} vertices and {@code E} edges.\n     * A rooted in-tree is a DAG in which there is a single vertex\n     * reachable from every other vertex.\n     * The DAG returned is not chosen uniformly at random among all such DAGs.\n     * @param V the number of vertices\n     * @param E the number of edges\n     * @return a random rooted-in DAG on {@code V} vertices and {@code E} edges\n     */\n    public static Digraph rootedInDAG(int V, int E) {\n        if (E > (long) V*(V-1) / 2) throw new IllegalArgumentException(\"Too many edges\");\n        if (E < V-1)                throw new IllegalArgumentException(\"Too few edges\");\n        Digraph digraph = new Digraph(V);\n        SET<Edge> set = new SET<Edge>();\n\n        // fix a topological order\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n\n        // one edge pointing from each vertex, other than the root = vertices[V-1]\n        for (int v = 0; v < V-1; v++) {\n            int w = StdRandom.uniformInt(v+1, V);\n            Edge e = new Edge(v, w);\n            set.add(e);\n            digraph.addEdge(vertices[v], vertices[w]);\n        }\n\n        while (digraph.E() < E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            Edge e = new Edge(v, w);\n            if ((v < w) && !set.contains(e)) {\n                set.add(e);\n                digraph.addEdge(vertices[v], vertices[w]);\n            }\n        }\n        return digraph;\n    }\n\n    /**\n     * Returns a complete rooted-out DAG on {@code V} vertices.\n     * A rooted out-tree is a DAG in which every vertex is reachable\n     * from a single vertex. A complete rooted in-DAG has V*(V-1)/2 edges.\n     * @param V the number of vertices\n     * @return a complete rooted-out DAG on {@code V} vertices\n     */\n    public static Digraph completeRootedOutDAG(int V) {\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V; i++)\n            for (int j = i+1; j < V; j++)\n                 digraph.addEdge(vertices[j], vertices[i]);\n\n        return digraph;\n    }\n\n    /**\n     * Returns a random rooted-out DAG on {@code V} vertices and {@code E} edges.\n     * A rooted out-tree is a DAG in which every vertex is reachable from a\n     * single vertex.\n     * The DAG returned is not chosen uniformly at random among all such DAGs.\n     * @param V the number of vertices\n     * @param E the number of edges\n     * @return a random rooted-out DAG on {@code V} vertices and {@code E} edges\n     */\n    public static Digraph rootedOutDAG(int V, int E) {\n        if (E > (long) V*(V-1) / 2) throw new IllegalArgumentException(\"Too many edges\");\n        if (E < V-1)                throw new IllegalArgumentException(\"Too few edges\");\n        Digraph digraph = new Digraph(V);\n        SET<Edge> set = new SET<Edge>();\n\n        // fix a topological order\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n\n        // one edge pointing from each vertex, other than the root = vertices[V-1]\n        for (int v = 0; v < V-1; v++) {\n            int w = StdRandom.uniformInt(v+1, V);\n            Edge e = new Edge(w, v);\n            set.add(e);\n            digraph.addEdge(vertices[w], vertices[v]);\n        }\n\n        while (digraph.E() < E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            Edge e = new Edge(w, v);\n            if ((v < w) && !set.contains(e)) {\n                set.add(e);\n                digraph.addEdge(vertices[w], vertices[v]);\n            }\n        }\n        return digraph;\n    }\n\n    /**\n     * Returns a random rooted-in tree on {@code V} vertices.\n     * A rooted in-tree is an oriented tree in which there is a single vertex\n     * reachable from every other vertex.\n     * The tree returned is not chosen uniformly at random among all such trees.\n     * @param V the number of vertices\n     * @return a random rooted-in tree on {@code V} vertices\n     */\n    public static Digraph rootedInTree(int V) {\n        return rootedInDAG(V, V-1);\n    }\n\n    /**\n     * Returns a random rooted-out tree on {@code V} vertices. A rooted out-tree\n     * is an oriented tree in which each vertex is reachable from a single vertex.\n     * It is also known as a <em>arborescence</em> or <em>branching</em>.\n     * The tree returned is not chosen uniformly at random among all such trees.\n     * @param V the number of vertices\n     * @return a random rooted-out tree on {@code V} vertices\n     */\n    public static Digraph rootedOutTree(int V) {\n        return rootedOutDAG(V, V-1);\n    }\n\n    /**\n     * Returns a path digraph on {@code V} vertices.\n     * @param V the number of vertices in the path\n     * @return a digraph that is a directed path on {@code V} vertices\n     */\n    public static Digraph path(int V) {\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V-1; i++) {\n            digraph.addEdge(vertices[i], vertices[i+1]);\n        }\n        return digraph;\n    }\n\n    /**\n     * Returns a complete binary tree digraph on {@code V} vertices.\n     * @param V the number of vertices in the binary tree\n     * @return a digraph that is a complete binary tree on {@code V} vertices\n     */\n    public static Digraph binaryTree(int V) {\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 1; i < V; i++) {\n            digraph.addEdge(vertices[i], vertices[(i-1)/2]);\n        }\n        return digraph;\n    }\n\n    /**\n     * Returns a cycle digraph on {@code V} vertices.\n     * @param V the number of vertices in the cycle\n     * @return a digraph that is a directed cycle on {@code V} vertices\n     */\n    public static Digraph cycle(int V) {\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V-1; i++) {\n            digraph.addEdge(vertices[i], vertices[i+1]);\n        }\n        digraph.addEdge(vertices[V-1], vertices[0]);\n        return digraph;\n    }\n\n    /**\n     * Returns an Eulerian cycle digraph on {@code V} vertices.\n     *\n     * @param  V the number of vertices in the cycle\n     * @param  E the number of edges in the cycle\n     * @return a digraph that is a directed Eulerian cycle on {@code V} vertices\n     *         and {@code E} edges\n     * @throws IllegalArgumentException if either {@code V <= 0} or {@code E <= 0}\n     */\n    public static Digraph eulerianCycle(int V, int E) {\n        if (E <= 0)\n            throw new IllegalArgumentException(\"An Eulerian cycle must have at least one edge\");\n        if (V <= 0)\n            throw new IllegalArgumentException(\"An Eulerian cycle must have at least one vertex\");\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[E];\n        for (int i = 0; i < E; i++)\n            vertices[i] = StdRandom.uniformInt(V);\n        for (int i = 0; i < E-1; i++) {\n            digraph.addEdge(vertices[i], vertices[i+1]);\n        }\n        digraph.addEdge(vertices[E-1], vertices[0]);\n        return digraph;\n    }\n\n    /**\n     * Returns an Eulerian path digraph on {@code V} vertices.\n     *\n     * @param  V the number of vertices in the path\n     * @param  E the number of edges in the path\n     * @return a digraph that is a directed Eulerian path on {@code V} vertices\n     *         and {@code E} edges\n     * @throws IllegalArgumentException if either {@code V <= 0} or {@code E < 0}\n     */\n    public static Digraph eulerianPath(int V, int E) {\n        if (E < 0)\n            throw new IllegalArgumentException(\"negative number of edges\");\n        if (V <= 0)\n            throw new IllegalArgumentException(\"An Eulerian path must have at least one vertex\");\n        Digraph digraph = new Digraph(V);\n        int[] vertices = new int[E+1];\n        for (int i = 0; i < E+1; i++)\n            vertices[i] = StdRandom.uniformInt(V);\n        for (int i = 0; i < E; i++) {\n            digraph.addEdge(vertices[i], vertices[i+1]);\n        }\n        return digraph;\n    }\n\n   /**\n     * Returns a random simple digraph on {@code V} vertices, {@code E}\n     * edges and (at least) {@code c} strong components. The vertices are randomly\n     * assigned integer labels between {@code 0} and {@code c-1} (corresponding to\n     * strong components). Then, a strong component is creates among the vertices\n     * with the same label. Next, random edges (either between two vertices with\n     * the same labels or from a vertex with a smaller label to a vertex with a\n     * larger label). The number of components will be equal to the number of\n     * distinct labels that are assigned to vertices.\n     *\n     * @param V the number of vertices\n     * @param E the number of edges\n     * @param c the (maximum) number of strong components\n     * @return a random simple digraph on {@code V} vertices and\n               {@code E} edges, with (at most) {@code c} strong components\n     * @throws IllegalArgumentException if {@code c} is larger than {@code V}\n     */\n    public static Digraph strong(int V, int E, int c) {\n        if (c >= V || c <= 0)\n            throw new IllegalArgumentException(\"Number of components must be between 1 and V\");\n        if (E <= 2*(V-c))\n            throw new IllegalArgumentException(\"Number of edges must be at least 2(V-c)\");\n        if (E > (long) V*(V-1) / 2)\n            throw new IllegalArgumentException(\"Too many edges\");\n\n        // the digraph\n        Digraph digraph = new Digraph(V);\n\n        // edges added to G (to avoid duplicate edges)\n        SET<Edge> set = new SET<Edge>();\n\n        int[] label = new int[V];\n        for (int v = 0; v < V; v++)\n            label[v] = StdRandom.uniformInt(c);\n\n        // make all vertices with label c a strong component by\n        // combining a rooted in-tree and a rooted out-tree\n        for (int i = 0; i < c; i++) {\n            // how many vertices in component c\n            int count = 0;\n            for (int v = 0; v < digraph.V(); v++) {\n                if (label[v] == i) count++;\n            }\n\n            // if (count == 0) System.err.println(\"less than desired number of strong components\");\n\n            int[] vertices = new int[count];\n            int j = 0;\n            for (int v = 0; v < V; v++) {\n                if (label[v] == i) vertices[j++] = v;\n            }\n            StdRandom.shuffle(vertices);\n\n            // rooted-in tree with root = vertices[count-1]\n            for (int v = 0; v < count-1; v++) {\n                int w = StdRandom.uniformInt(v+1, count);\n                Edge e = new Edge(w, v);\n                set.add(e);\n                digraph.addEdge(vertices[w], vertices[v]);\n            }\n\n            // rooted-out tree with root = vertices[count-1]\n            for (int v = 0; v < count-1; v++) {\n                int w = StdRandom.uniformInt(v+1, count);\n                Edge e = new Edge(v, w);\n                set.add(e);\n                digraph.addEdge(vertices[v], vertices[w]);\n            }\n        }\n\n        while (digraph.E() < E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            Edge e = new Edge(v, w);\n            if (!set.contains(e) && v != w && label[v] <= label[w]) {\n                set.add(e);\n                digraph.addEdge(v, w);\n            }\n        }\n\n        return digraph;\n    }\n\n    /**\n     * Unit tests the {@code DigraphGenerator} library.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        StdOut.println(\"complete graph\");\n        StdOut.println(complete(V));\n        StdOut.println();\n\n        StdOut.println(\"simple\");\n        StdOut.println(simple(V, E));\n        StdOut.println();\n\n        StdOut.println(\"path\");\n        StdOut.println(path(V));\n        StdOut.println();\n\n        StdOut.println(\"cycle\");\n        StdOut.println(cycle(V));\n        StdOut.println();\n\n        StdOut.println(\"Eulierian path\");\n        StdOut.println(eulerianPath(V, E));\n        StdOut.println();\n\n        StdOut.println(\"Eulierian cycle\");\n        StdOut.println(eulerianCycle(V, E));\n        StdOut.println();\n\n        StdOut.println(\"binary tree\");\n        StdOut.println(binaryTree(V));\n        StdOut.println();\n\n        StdOut.println(\"tournament\");\n        StdOut.println(tournament(V));\n        StdOut.println();\n\n        StdOut.println(\"DAG\");\n        StdOut.println(dag(V, E));\n        StdOut.println();\n\n        StdOut.println(\"rooted-in DAG\");\n        StdOut.println(rootedInDAG(V, E));\n        StdOut.println();\n\n        StdOut.println(\"rooted-out DAG\");\n        StdOut.println(rootedOutDAG(V, E));\n        StdOut.println();\n\n        StdOut.println(\"rooted-in tree\");\n        StdOut.println(rootedInTree(V));\n        StdOut.println();\n\n        StdOut.println(\"rooted-out DAG\");\n        StdOut.println(rootedOutTree(V));\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DijkstraAllPairsSP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DijkstraAllPairsSP.java\n *  Execution:    none\n *  Dependencies: EdgeWeightedDigraph.java Dijkstra.java\n *\n *  Dijkstra's algorithm run from each vertex.\n *  Takes time proportional to E V log V and space proportional to EV.\n *\n *  % java DijkstraAllPairsSP tinyEWD.txt\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DijkstraAllPairsSP} class represents a data type for solving the\n *  all-pairs shortest paths problem in edge-weighted digraphs\n *  where the edge weights are non-negative.\n *  <p>\n *  This implementation runs Dijkstra's algorithm from each vertex.\n *  The constructor takes &Theta;(<em>V</em> (<em>E</em> log <em>V</em>)) time\n *  in the worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em><sup>2</sup>) extra space (not including the\n *  edge-weighted digraph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DijkstraAllPairsSP {\n    private DijkstraSP[] all;\n\n    /**\n     * Computes a shortest paths tree from each vertex to every other vertex in\n     * the edge-weighted digraph {@code G}.\n     * @param G the edge-weighted digraph\n     * @throws IllegalArgumentException if an edge weight is negative\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DijkstraAllPairsSP(EdgeWeightedDigraph G) {\n        all  = new DijkstraSP[G.V()];\n        for (int v = 0; v < G.V(); v++)\n            all[v] = new DijkstraSP(G, v);\n    }\n\n    /**\n     * Returns a shortest path from vertex {@code s} to vertex {@code t}.\n     * @param  s the source vertex\n     * @param  t the destination vertex\n     * @return a shortest path from vertex {@code s} to vertex {@code t}\n     *         as an iterable of edges, and {@code null} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     * @throws IllegalArgumentException unless {@code 0 <= t < V}\n     */\n    public Iterable<DirectedEdge> path(int s, int t) {\n        validateVertex(s);\n        validateVertex(t);\n        return all[s].pathTo(t);\n    }\n\n    /**\n     * Is there a path from the vertex {@code s} to vertex {@code t}?\n     * @param  s the source vertex\n     * @param  t the destination vertex\n     * @return {@code true} if there is a path from vertex {@code s}\n     *         to vertex {@code t}, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     * @throws IllegalArgumentException unless {@code 0 <= t < V}\n     */\n    public boolean hasPath(int s, int t) {\n        validateVertex(s);\n        validateVertex(t);\n        return dist(s, t) < Double.POSITIVE_INFINITY;\n    }\n\n    /**\n     * Returns the length of a shortest path from vertex {@code s} to vertex {@code t}.\n     * @param  s the source vertex\n     * @param  t the destination vertex\n     * @return the length of a shortest path from vertex {@code s} to vertex {@code t};\n     *         {@code Double.POSITIVE_INFINITY} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     * @throws IllegalArgumentException unless {@code 0 <= t < V}\n     */\n    public double dist(int s, int t) {\n        validateVertex(s);\n        validateVertex(t);\n        return all[s].distTo(t);\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = all.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n\n    /**\n     * Unit tests the {@code DijkstraAllPairsSP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read edge-weighted digraph\n        In in = new In(args[0]);\n        EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);\n\n        // compute shortest paths between all pairs of vertices\n        DijkstraAllPairsSP spt = new DijkstraAllPairsSP(G);\n\n        // print all-pairs shortest path distances\n        StdOut.printf(\"  \");\n        for (int v = 0; v < G.V(); v++) {\n            StdOut.printf(\"%6d \", v);\n        }\n        StdOut.println();\n        for (int v = 0; v < G.V(); v++) {\n            StdOut.printf(\"%3d: \", v);\n            for (int w = 0; w < G.V(); w++) {\n                if (spt.hasPath(v, w)) StdOut.printf(\"%6.2f \", spt.dist(v, w));\n                else StdOut.printf(\"  Inf \");\n            }\n            StdOut.println();\n        }\n        StdOut.println();\n\n        // print all-pairs shortest paths\n        for (int v = 0; v < G.V(); v++) {\n            for (int w = 0; w < G.V(); w++) {\n                if (spt.hasPath(v, w)) {\n                    StdOut.printf(\"%d to %d (%5.2f)  \", v, w, spt.dist(v, w));\n                    for (DirectedEdge e : spt.path(v, w))\n                        StdOut.print(e + \"  \");\n                    StdOut.println();\n                }\n                else {\n                    StdOut.printf(\"%d to %d no path\\n\", v, w);\n                }\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DijkstraSP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DijkstraSP.java\n *  Execution:    java DijkstraSP input.txt s\n *  Dependencies: EdgeWeightedDigraph.java IndexMinPQ.java Stack.java DirectedEdge.java\n *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWD.txt\n *                https://algs4.cs.princeton.edu/44sp/mediumEWD.txt\n *                https://algs4.cs.princeton.edu/44sp/largeEWD.txt\n *\n *  Dijkstra's algorithm. Computes the shortest path tree.\n *  Assumes all weights are non-negative.\n *\n *  % java DijkstraSP tinyEWD.txt 0\n *  0 to 0 (0.00)\n *  0 to 1 (1.05)  0->4  0.38   4->5  0.35   5->1  0.32\n *  0 to 2 (0.26)  0->2  0.26\n *  0 to 3 (0.99)  0->2  0.26   2->7  0.34   7->3  0.39\n *  0 to 4 (0.38)  0->4  0.38\n *  0 to 5 (0.73)  0->4  0.38   4->5  0.35\n *  0 to 6 (1.51)  0->2  0.26   2->7  0.34   7->3  0.39   3->6  0.52\n *  0 to 7 (0.60)  0->2  0.26   2->7  0.34\n *\n *  % java DijkstraSP mediumEWD.txt 0\n *  0 to 0 (0.00)\n *  0 to 1 (0.71)  0->44  0.06   44->93  0.07   ...  107->1  0.07\n *  0 to 2 (0.65)  0->44  0.06   44->231  0.10  ...  42->2  0.11\n *  0 to 3 (0.46)  0->97  0.08   97->248  0.09  ...  45->3  0.12\n *  0 to 4 (0.42)  0->44  0.06   44->93  0.07   ...  77->4  0.11\n *  ...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code DijkstraSP} class represents a data type for solving the\n *  single-source shortest paths problem in edge-weighted digraphs\n *  where the edge weights are non-negative.\n *  <p>\n *  This implementation uses <em>Dijkstra's algorithm</em> with a\n *  <em>binary heap</em>. The constructor takes\n *  &Theta;(<em>E</em> log <em>V</em>) time in the worst case,\n *  where <em>V</em> is the number of vertices and <em>E</em> is\n *  the number of edges. Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted digraph).\n *  <p>\n *  This correctly computes shortest paths if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>. Since all intermediate\n *  results are sums of edge weights, they are bounded by <em>V C</em>,\n *  where <em>V</em> is the number of vertices and <em>C</em> is the maximum\n *  weight of any edge.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DijkstraSP {\n    private double[] distTo;          // distTo[v] = distance  of shortest s->v path\n    private DirectedEdge[] edgeTo;    // edgeTo[v] = last edge on shortest s->v path\n    private IndexMinPQ<Double> pq;    // priority queue of vertices\n\n    /**\n     * Computes a shortest-paths tree from the source vertex {@code s} to every other\n     * vertex in the edge-weighted {@code digraph}.\n     *\n     * @param  digraph the edge-weighted digraph\n     * @param  s the source vertex\n     * @throws IllegalArgumentException if an edge weight is negative\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DijkstraSP(EdgeWeightedDigraph digraph, int s) {\n        for (DirectedEdge e : digraph.edges()) {\n            if (e.weight() < 0)\n                throw new IllegalArgumentException(\"edge \" + e + \" has negative weight\");\n        }\n\n        distTo = new double[digraph.V()];\n        edgeTo = new DirectedEdge[digraph.V()];\n\n        validateVertex(s);\n\n        for (int v = 0; v < digraph.V(); v++)\n            distTo[v] = Double.POSITIVE_INFINITY;\n        distTo[s] = 0.0;\n\n        // relax vertices in order of distance from s\n        pq = new IndexMinPQ<Double>(digraph.V());\n        pq.insert(s, distTo[s]);\n        while (!pq.isEmpty()) {\n            int v = pq.delMin();\n            for (DirectedEdge e : digraph.adj(v))\n                relax(e);\n        }\n\n        // check optimality conditions\n        assert check(digraph, s);\n    }\n\n    // relax edge e and update pq if changed\n    private void relax(DirectedEdge e) {\n        int v = e.from(), w = e.to();\n        if (distTo[w] > distTo[v] + e.weight()) {\n            distTo[w] = distTo[v] + e.weight();\n            edgeTo[w] = e;\n            if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);\n            else                pq.insert(w, distTo[w]);\n        }\n    }\n\n    /**\n     * Returns the length of a shortest path from the source vertex {@code s} to vertex {@code v}.\n     * @param  v the destination vertex\n     * @return the length of a shortest path from the source vertex {@code s} to vertex {@code v};\n     *         {@code Double.POSITIVE_INFINITY} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public double distTo(int v) {\n        validateVertex(v);\n        return distTo[v];\n    }\n\n    /**\n     * Returns true if there is a path from the source vertex {@code s} to vertex {@code v}.\n     *\n     * @param  v the destination vertex\n     * @return {@code true} if there is a path from the source vertex\n     *         {@code s} to vertex {@code v}; {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return distTo[v] < Double.POSITIVE_INFINITY;\n    }\n\n    /**\n     * Returns a shortest path from the source vertex {@code s} to vertex {@code v}.\n     *\n     * @param  v the destination vertex\n     * @return a shortest path from the source vertex {@code s} to vertex {@code v}\n     *         as an iterable of edges, and {@code null} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<DirectedEdge> path = new Stack<DirectedEdge>();\n        for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {\n            path.push(e);\n        }\n        return path;\n    }\n\n\n    // check optimality conditions:\n    // (i) for all edges e:            distTo[e.to()] <= distTo[e.from()] + e.weight()\n    // (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight()\n    private boolean check(EdgeWeightedDigraph digraph, int s) {\n\n        // check that edge weights are non-negative\n        for (DirectedEdge e : digraph.edges()) {\n            if (e.weight() < 0) {\n                System.err.println(\"negative edge weight detected\");\n                return false;\n            }\n        }\n\n        // check that distTo[v] and edgeTo[v] are consistent\n        if (distTo[s] != 0.0 || edgeTo[s] != null) {\n            System.err.println(\"distTo[s] and edgeTo[s] inconsistent\");\n            return false;\n        }\n        for (int v = 0; v < digraph.V(); v++) {\n            if (v == s) continue;\n            if (edgeTo[v] == null && distTo[v] != Double.POSITIVE_INFINITY) {\n                System.err.println(\"distTo[] and edgeTo[] inconsistent\");\n                return false;\n            }\n        }\n\n        // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()\n        for (int v = 0; v < digraph.V(); v++) {\n            for (DirectedEdge e : digraph.adj(v)) {\n                int w = e.to();\n                if (distTo[v] + e.weight() < distTo[w]) {\n                    System.err.println(\"edge \" + e + \" not relaxed\");\n                    return false;\n                }\n            }\n        }\n\n        // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()\n        for (int w = 0; w < digraph.V(); w++) {\n            if (edgeTo[w] == null) continue;\n            DirectedEdge e = edgeTo[w];\n            int v = e.from();\n            if (w != e.to()) return false;\n            if (distTo[v] + e.weight() != distTo[w]) {\n                System.err.println(\"edge \" + e + \" on shortest path not tight\");\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = distTo.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code DijkstraSP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedDigraph digraph = new EdgeWeightedDigraph(in);\n        int s = Integer.parseInt(args[1]);\n\n        // compute shortest paths\n        DijkstraSP sp = new DijkstraSP(digraph, s);\n\n\n        // print shortest path\n        for (int t = 0; t < digraph.V(); t++) {\n            if (sp.hasPathTo(t)) {\n                StdOut.printf(\"%d to %d (%.2f)  \", s, t, sp.distTo(t));\n                for (DirectedEdge e : sp.pathTo(t)) {\n                    StdOut.print(e + \"   \");\n                }\n                StdOut.println();\n            }\n            else {\n                StdOut.printf(\"%d to %d         no path\\n\", s, t);\n            }\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DijkstraUndirectedSP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DijkstraUndirectedSP.java\n *  Execution:    java DijkstraUndirectedSP input.txt s\n *  Dependencies: EdgeWeightedGraph.java IndexMinPQ.java Stack.java Edge.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt\n *\n *  Dijkstra's algorithm. Computes the shortest path tree.\n *  Assumes all weights are non-negative.\n *\n *  % java DijkstraUndirectedSP tinyEWG.txt 6\n *  6 to 0 (0.58)  6-0 0.58000\n *  6 to 1 (0.76)  6-2 0.40000   1-2 0.36000\n *  6 to 2 (0.40)  6-2 0.40000\n *  6 to 3 (0.52)  3-6 0.52000\n *  6 to 4 (0.93)  6-4 0.93000\n *  6 to 5 (1.02)  6-2 0.40000   2-7 0.34000   5-7 0.28000\n *  6 to 6 (0.00)\n *  6 to 7 (0.74)  6-2 0.40000   2-7 0.34000\n *\n *  % java DijkstraUndirectedSP mediumEWG.txt 0\n *  0 to 0 (0.00)\n *  0 to 1 (0.71)  0-44 0.06471   44-93  0.06793  ...   1-107 0.07484\n *  0 to 2 (0.65)  0-44 0.06471   44-231 0.10384  ...   2-42  0.11456\n *  0 to 3 (0.46)  0-97 0.07705   97-248 0.08598  ...   3-45  0.11902\n *  ...\n *\n *  % java DijkstraUndirectedSP largeEWG.txt 0\n *  0 to 0 (0.00)\n *  0 to 1 (0.78)  0-460790 0.00190  460790-696678 0.00173   ...   1-826350 0.00191\n *  0 to 2 (0.61)  0-15786  0.00130  15786-53370   0.00113   ...   2-793420 0.00040\n *  0 to 3 (0.31)  0-460790 0.00190  460790-752483 0.00194   ...   3-698373 0.00172\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code DijkstraUndirectedSP} class represents a data type for solving\n *  the single-source shortest paths problem in edge-weighted graphs\n *  where the edge weights are non-negative.\n *  <p>\n *  This implementation uses Dijkstra's algorithm with a binary heap.\n *  The constructor takes &Theta;(<em>E</em> log <em>V</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted graph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  See {@link DijkstraSP} for a version on edge-weighted digraphs.\n *  <p>\n *  This correctly computes shortest paths if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>. Since all intermediate\n *  results are sums of edge weights, they are bounded by <em>V C</em>,\n *  where <em>V</em> is the number of vertices and <em>C</em> is the maximum\n *  weight of any edge.\n *  <p>\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *  @author Nate Liu\n */\npublic class DijkstraUndirectedSP {\n    private double[] distTo;          // distTo[v] = distance  of shortest s->v path\n    private Edge[] edgeTo;            // edgeTo[v] = last edge on shortest s->v path\n    private IndexMinPQ<Double> pq;    // priority queue of vertices\n\n    /**\n     * Computes a shortest-paths tree from the source vertex {@code s} to every\n     * other vertex in the edge-weighted graph {@code G}.\n     *\n     * @param  G the edge-weighted digraph\n     * @param  s the source vertex\n     * @throws IllegalArgumentException if an edge weight is negative\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DijkstraUndirectedSP(EdgeWeightedGraph G, int s) {\n        for (Edge e : G.edges()) {\n            if (e.weight() < 0)\n                throw new IllegalArgumentException(\"edge \" + e + \" has negative weight\");\n        }\n\n        distTo = new double[G.V()];\n        edgeTo = new Edge[G.V()];\n\n        validateVertex(s);\n\n        for (int v = 0; v < G.V(); v++)\n            distTo[v] = Double.POSITIVE_INFINITY;\n        distTo[s] = 0.0;\n\n        // relax vertices in order of distance from s\n        pq = new IndexMinPQ<Double>(G.V());\n        pq.insert(s, distTo[s]);\n        while (!pq.isEmpty()) {\n            int v = pq.delMin();\n            for (Edge e : G.adj(v))\n                relax(e, v);\n        }\n\n        // check optimality conditions\n        assert check(G, s);\n    }\n\n    // relax edge e and update pq if changed\n    private void relax(Edge e, int v) {\n        int w = e.other(v);\n        if (distTo[w] > distTo[v] + e.weight()) {\n            distTo[w] = distTo[v] + e.weight();\n            edgeTo[w] = e;\n            if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);\n            else                pq.insert(w, distTo[w]);\n        }\n    }\n\n    /**\n     * Returns the length of a shortest path between the source vertex {@code s} and\n     * vertex {@code v}.\n     *\n     * @param  v the destination vertex\n     * @return the length of a shortest path between the source vertex {@code s} and\n     *         the vertex {@code v}; {@code Double.POSITIVE_INFINITY} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public double distTo(int v) {\n        validateVertex(v);\n        return distTo[v];\n    }\n\n    /**\n     * Returns true if there is a path between the source vertex {@code s} and\n     * vertex {@code v}.\n     *\n     * @param  v the destination vertex\n     * @return {@code true} if there is a path between the source vertex\n     *         {@code s} to vertex {@code v}; {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean hasPathTo(int v) {\n        validateVertex(v);\n        return distTo[v] < Double.POSITIVE_INFINITY;\n    }\n\n    /**\n     * Returns a shortest path between the source vertex {@code s} and vertex {@code v}.\n     *\n     * @param  v the destination vertex\n     * @return a shortest path between the source vertex {@code s} and vertex {@code v};\n     *         {@code null} if no such path\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Edge> pathTo(int v) {\n        validateVertex(v);\n        if (!hasPathTo(v)) return null;\n        Stack<Edge> path = new Stack<Edge>();\n        int x = v;\n        for (Edge e = edgeTo[v]; e != null; e = edgeTo[x]) {\n            path.push(e);\n            x = e.other(x);\n        }\n        return path;\n    }\n\n\n    // check optimality conditions:\n    // (i) for all edges e = v-w:            distTo[w] <= distTo[v] + e.weight()\n    // (ii) for all edge e = v-w on the SPT: distTo[w] == distTo[v] + e.weight()\n    private boolean check(EdgeWeightedGraph G, int s) {\n\n        // check that edge weights are non-negative\n        for (Edge e : G.edges()) {\n            if (e.weight() < 0) {\n                System.err.println(\"negative edge weight detected\");\n                return false;\n            }\n        }\n\n        // check that distTo[v] and edgeTo[v] are consistent\n        if (distTo[s] != 0.0 || edgeTo[s] != null) {\n            System.err.println(\"distTo[s] and edgeTo[s] inconsistent\");\n            return false;\n        }\n        for (int v = 0; v < G.V(); v++) {\n            if (v == s) continue;\n            if (edgeTo[v] == null && distTo[v] != Double.POSITIVE_INFINITY) {\n                System.err.println(\"distTo[] and edgeTo[] inconsistent\");\n                return false;\n            }\n        }\n\n        // check that all edges e = v-w satisfy distTo[w] <= distTo[v] + e.weight()\n        for (int v = 0; v < G.V(); v++) {\n            for (Edge e : G.adj(v)) {\n                int w = e.other(v);\n                if (distTo[v] + e.weight() < distTo[w]) {\n                    System.err.println(\"edge \" + e + \" not relaxed\");\n                    return false;\n                }\n            }\n        }\n\n        // check that all edges e = v-w on SPT satisfy distTo[w] == distTo[v] + e.weight()\n        for (int w = 0; w < G.V(); w++) {\n            if (edgeTo[w] == null) continue;\n            Edge e = edgeTo[w];\n            if (w != e.either() && w != e.other(e.either())) return false;\n            int v = e.other(w);\n            if (distTo[v] + e.weight() != distTo[w]) {\n                System.err.println(\"edge \" + e + \" on shortest path not tight\");\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = distTo.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code DijkstraUndirectedSP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph G = new EdgeWeightedGraph(in);\n        int s = Integer.parseInt(args[1]);\n\n        // compute shortest paths\n        DijkstraUndirectedSP sp = new DijkstraUndirectedSP(G, s);\n\n\n        // print shortest path\n        for (int t = 0; t < G.V(); t++) {\n            if (sp.hasPathTo(t)) {\n                StdOut.printf(\"%d to %d (%.2f)  \", s, t, sp.distTo(t));\n                for (Edge e : sp.pathTo(t)) {\n                    StdOut.print(e + \"   \");\n                }\n                StdOut.println();\n            }\n            else {\n                StdOut.printf(\"%d to %d         no path\\n\", s, t);\n            }\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DirectedCycle.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DirectedCycle.java\n *  Execution:    java DirectedCycle input.txt\n *  Dependencies: Digraph.java Stack.java StdOut.java In.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt\n *\n *  Finds a directed cycle in a digraph.\n *\n *  % java DirectedCycle tinyDG.txt\n *  Directed cycle: 3 5 4 3\n *\n *  %  java DirectedCycle tinyDAG.txt\n *  No directed cycle\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DirectedCycle} class represents a data type for\n *  determining whether a digraph has a directed cycle.\n *  The <em>hasCycle</em> operation determines whether the digraph has\n *  a simple directed cycle and, if so, the <em>cycle</em> operation\n *  returns one.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the worst\n *  case, where <em>V</em> is the number of vertices and <em>E</em> is\n *  the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  See {@link Topological} to compute a topological order if the\n *  digraph is acyclic.\n *  See {@link DirectedCycleX} for a nonrecursive, queue-based implementation.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DirectedCycle {\n    private boolean[] marked;        // marked[v] = has vertex v been marked?\n    private int[] edgeTo;            // edgeTo[v] = previous vertex on path to v\n    private boolean[] onStack;       // onStack[v] = is vertex on the stack?\n    private Stack<Integer> cycle;    // directed cycle (or null if no such cycle)\n\n    /**\n     * Determines whether {@code digraph} has a directed cycle and, if so,\n     * finds such a cycle.\n     * @param digraph the digraph\n     */\n    public DirectedCycle(Digraph digraph) {\n        marked  = new boolean[digraph.V()];\n        onStack = new boolean[digraph.V()];\n        edgeTo  = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            if (!marked[v] && cycle == null) dfs(digraph, v);\n    }\n\n    // run DFS and find a directed cycle (if one exists)\n    private void dfs(Digraph digraph, int v) {\n        onStack[v] = true;\n        marked[v] = true;\n        for (int w : digraph.adj(v)) {\n\n            // short circuit if directed cycle found\n            if (cycle != null) return;\n\n            // found new vertex, so recur\n            else if (!marked[w]) {\n                edgeTo[w] = v;\n                dfs(digraph, w);\n            }\n\n            // trace back directed cycle\n            else if (onStack[w]) {\n                cycle = new Stack<Integer>();\n                for (int x = v; x != w; x = edgeTo[x]) {\n                    cycle.push(x);\n                }\n                cycle.push(w);\n                cycle.push(v);\n                assert check();\n            }\n        }\n        onStack[v] = false;\n    }\n\n    /**\n     * Does the digraph have a directed cycle?\n     * @return {@code true} if the digraph has a directed cycle, {@code false} otherwise\n     */\n    public boolean hasCycle() {\n        return cycle != null;\n    }\n\n    /**\n     * Returns a directed cycle if the digraph has a directed cycle, and {@code null} otherwise.\n     * @return a directed cycle (as an iterable) if the digraph has a directed cycle,\n     *    and {@code null} otherwise\n     */\n    public Iterable<Integer> cycle() {\n        return cycle;\n    }\n\n\n    // certify that digraph has a directed cycle if it reports one\n    private boolean check() {\n\n        if (hasCycle()) {\n            // verify cycle\n            int first = -1, last = -1;\n            for (int v : cycle()) {\n                if (first == -1) first = v;\n                last = v;\n            }\n            if (first != last) {\n                System.err.printf(\"cycle begins with %d and ends with %d\\n\", first, last);\n                return false;\n            }\n        }\n\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code DirectedCycle} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n\n        DirectedCycle finder = new DirectedCycle(digraph);\n        if (finder.hasCycle()) {\n            StdOut.print(\"Directed cycle: \");\n            for (int v : finder.cycle()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n\n        else {\n            StdOut.println(\"No directed cycle\");\n        }\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DirectedCycleX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DirectedCycleX.java\n *  Execution:    java DirectedCycleX V E F\n *  Dependencies: Queue.java Digraph.java Stack.java\n *\n *  Find a directed cycle in a digraph, using a nonrecursive, queue-based\n *  algorithm. Runs in O(E + V) time.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DirectedCycleX} class represents a data type for\n *  determining whether a digraph has a directed cycle.\n *  The <em>hasCycle</em> operation determines whether the digraph has\n *  a simple directed cycle and, if so, the <em>cycle</em> operation\n *  returns one.\n *  <p>\n *  This implementation uses a nonrecursive, queue-based algorithm.\n *  The constructor takes time proportional to <em>V</em> + <em>E</em>\n *  (in the worst case),\n *  where <em>V</em> is the number of vertices and <em>E</em> is the\n *  number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  See {@link DirectedCycle} for a recursive version that uses depth-first search.\n *  See {@link Topological} or {@link TopologicalX} to compute a topological order\n *  when the digraph is acyclic.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class DirectedCycleX {\n    private Stack<Integer> cycle;     // the directed cycle; null if digraph is acyclic\n\n    public DirectedCycleX(Digraph digraph) {\n\n        // indegrees of remaining vertices\n        int[] indegree = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++) {\n            indegree[v] = digraph.indegree(v);\n        }\n\n        // initialize queue to contain all vertices with indegree = 0\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int v = 0; v < digraph.V(); v++)\n            if (indegree[v] == 0) queue.enqueue(v);\n\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : digraph.adj(v)) {\n                indegree[w]--;\n                if (indegree[w] == 0) queue.enqueue(w);\n            }\n        }\n\n        // there is a directed cycle in subgraph of vertices with indegree >= 1.\n        int[] edgeTo = new int[digraph.V()];\n        int root = -1;  // any vertex with indegree >= -1\n        for (int v = 0; v < digraph.V(); v++) {\n            if (indegree[v] == 0) continue;\n            else root = v;\n            for (int w : digraph.adj(v)) {\n                if (indegree[w] > 0) {\n                    edgeTo[w] = v;\n                }\n            }\n        }\n\n        if (root != -1) {\n\n            // find any vertex on cycle\n            boolean[] visited = new boolean[digraph.V()];\n            while (!visited[root]) {\n                visited[root] = true;\n                root = edgeTo[root];\n            }\n\n            // extract cycle\n            cycle = new Stack<Integer>();\n            int v = root;\n            do {\n                cycle.push(v);\n                v = edgeTo[v];\n            } while (v != root);\n            cycle.push(root);\n        }\n\n        assert check();\n    }\n\n    /**\n     * Returns a directed cycle if the digraph has a directed cycle, and {@code null} otherwise.\n     * @return a directed cycle (as an iterable) if the digraph has a directed cycle,\n     *    and {@code null} otherwise\n     */\n    public Iterable<Integer> cycle() {\n        return cycle;\n    }\n\n    /**\n     * Does the digraph have a directed cycle?\n     * @return {@code true} if the digraph has a directed cycle, {@code false} otherwise\n     */\n    public boolean hasCycle() {\n        return cycle != null;\n    }\n\n    // certify that digraph has a directed cycle if it reports one\n    private boolean check() {\n\n        if (hasCycle()) {\n            // verify cycle\n            int first = -1, last = -1;\n            for (int v : cycle()) {\n                if (first == -1) first = v;\n                last = v;\n            }\n            if (first != last) {\n                System.err.printf(\"cycle begins with %d and ends with %d\\n\", first, last);\n                return false;\n            }\n        }\n\n\n        return true;\n    }\n\n\n    public static void main(String[] args) {\n\n        // create random DAG with V vertices and E edges; then add F random edges\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        int F = Integer.parseInt(args[2]);\n        Digraph digraph = DigraphGenerator.dag(V, E);\n\n        // add F extra edges\n        for (int i = 0; i < F; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            digraph.addEdge(v, w);\n        }\n\n        StdOut.println(digraph);\n\n\n        DirectedCycleX finder = new DirectedCycleX(digraph);\n        if (finder.hasCycle()) {\n            StdOut.print(\"Directed cycle: \");\n            for (int v : finder.cycle()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n\n        else {\n            StdOut.println(\"No directed cycle\");\n        }\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DirectedDFS.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DirectedDFS.java\n *  Execution:    java DirectedDFS digraph.txt s\n *  Dependencies: Digraph.java Bag.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Determine single-source or multiple-source reachability in a digraph\n *  using depth first search.\n *  Runs in O(E + V) time.\n *\n *  % java DirectedDFS tinyDG.txt 1\n *  1\n *\n *  % java DirectedDFS tinyDG.txt 2\n *  0 1 2 3 4 5\n *\n *  % java DirectedDFS tinyDG.txt 1 2 6\n *  0 1 2 3 4 5 6 8 9 10 11 12\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n/**\n *  The {@code DirectedDFS} class represents a data type for\n *  determining the vertices reachable from a given source vertex <em>s</em>\n *  (or set of source vertices) in a digraph. For versions that find the paths,\n *  see {@link DepthFirstDirectedPaths} and {@link BreadthFirstDirectedPaths}.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes time proportional to <em>V</em> + <em>E</em>\n *  (in the worst case),\n *  where <em>V</em> is the number of vertices and <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  See {@link NonrecursiveDirectedDFS} for a nonrecursive implementation.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DirectedDFS {\n    private boolean[] marked;  // marked[v] = true iff v is reachable from source(s)\n    private int count;         // number of vertices reachable from source(s)\n\n    /**\n     * Computes the vertices in a digraph that are\n     * reachable from a source vertex.\n     * @param digraph the digraph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public DirectedDFS(Digraph digraph, int s) {\n        marked = new boolean[digraph.V()];\n        validateVertex(s);\n        dfs(digraph, s);\n    }\n\n    /**\n     * Computes the vertices in a digraph that are\n     * connected to any of a set of source vertices.\n     * @param digraph the graph\n     * @param sources the source vertices\n     * @throws IllegalArgumentException if {@code sources} is {@code null}\n     * @throws IllegalArgumentException if {@code sources} contains no vertices\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     *         for each vertex {@code s} in {@code sources}\n     */\n    public DirectedDFS(Digraph digraph, Iterable<Integer> sources) {\n        marked = new boolean[digraph.V()];\n        validateVertices(sources);\n        for (int v : sources) {\n            if (!marked[v]) dfs(digraph, v);\n        }\n    }\n\n    private void dfs(Digraph digraph, int v) {\n        count++;\n        marked[v] = true;\n        for (int w : digraph.adj(v)) {\n            if (!marked[w]) dfs(digraph, w);\n        }\n    }\n\n    /**\n     * Is there a directed path from the source vertex (or any\n     * of the source vertices) and vertex {@code v}?\n     * @param  v the vertex\n     * @return {@code true} if there is a directed path, {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean marked(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    /**\n     * Returns the number of vertices reachable from the source vertex\n     * (or source vertices).\n     * @return the number of vertices reachable from the source vertex\n     *   (or source vertices)\n     */\n    public int count() {\n        return count;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    // throw an IllegalArgumentException if vertices is null, has zero vertices,\n    // or has a vertex not between 0 and V-1\n    private void validateVertices(Iterable<Integer> vertices) {\n        if (vertices == null) {\n            throw new IllegalArgumentException(\"argument is null\");\n        }\n        int vertexCount = 0;\n        for (Integer v : vertices) {\n            vertexCount++;\n            if (v == null) {\n                throw new IllegalArgumentException(\"vertex is null\");\n            }\n            validateVertex(v);\n        }\n        if (vertexCount == 0) {\n            throw new IllegalArgumentException(\"zero vertices\");\n        }\n    }\n\n    /**\n     * Unit tests the {@code DirectedDFS} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read in digraph from command-line argument\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n\n        // read in sources from command-line arguments\n        Bag<Integer> sources = new Bag<Integer>();\n        for (int i = 1; i < args.length; i++) {\n            int s = Integer.parseInt(args[i]);\n            sources.add(s);\n        }\n\n        // multiple-source reachability\n        DirectedDFS dfs = new DirectedDFS(digraph, sources);\n\n        // print out vertices reachable from sources\n        for (int v = 0; v < digraph.V(); v++) {\n            if (dfs.marked(v)) StdOut.print(v + \" \");\n        }\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DirectedEdge.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DirectedEdge.java\n *  Execution:    java DirectedEdge\n *  Dependencies: StdOut.java\n *\n *  Immutable weighted directed edge.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n/**\n *  The {@code DirectedEdge} class represents a weighted edge in an\n *  {@link EdgeWeightedDigraph}. Each edge consists of two integers\n *  (naming the two vertices) and a real-value weight. The data type\n *  provides methods for accessing the two endpoints of the directed edge and\n *  the weight.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class DirectedEdge {\n    private final int v;\n    private final int w;\n    private final double weight;\n\n    /**\n     * Initializes a directed edge from vertex {@code v} to vertex {@code w} with\n     * the given {@code weight}.\n     * @param v the tail vertex\n     * @param w the head vertex\n     * @param weight the weight of the directed edge\n     * @throws IllegalArgumentException if either {@code v} or {@code w}\n     *    is a negative integer\n     * @throws IllegalArgumentException if {@code weight} is {@code NaN}\n     */\n    public DirectedEdge(int v, int w, double weight) {\n        if (v < 0) throw new IllegalArgumentException(\"Vertex names must be non-negative integers\");\n        if (w < 0) throw new IllegalArgumentException(\"Vertex names must be non-negative integers\");\n        if (Double.isNaN(weight)) throw new IllegalArgumentException(\"Weight is NaN\");\n        this.v = v;\n        this.w = w;\n        this.weight = weight;\n    }\n\n    /**\n     * Returns the tail vertex of the directed edge.\n     * @return the tail vertex of the directed edge\n     */\n    public int from() {\n        return v;\n    }\n\n    /**\n     * Returns the head vertex of the directed edge.\n     * @return the head vertex of the directed edge\n     */\n    public int to() {\n        return w;\n    }\n\n    /**\n     * Returns the weight of the directed edge.\n     * @return the weight of the directed edge\n     */\n    public double weight() {\n        return weight;\n    }\n\n    /**\n     * Returns a string representation of the directed edge.\n     * @return a string representation of the directed edge\n     */\n    public String toString() {\n        return v + \"->\" + w + \" \" + String.format(\"%5.2f\", weight);\n    }\n\n    /**\n     * Unit tests the {@code DirectedEdge} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        DirectedEdge e = new DirectedEdge(12, 34, 5.67);\n        StdOut.println(e);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DirectedEulerianCycle.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DirectedEulerianCycle.java\n *  Execution:    java DirectedEulerianCycle V E\n *  Dependencies: Digraph.java Stack.java StdOut.java\n *                BreadthFirstPaths.java\n *                DigraphGenerator.java StdRandom.java\n *\n *  Find an Eulerian cycle in a digraph, if one exists.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code DirectedEulerianCycle} class represents a data type\n *  for finding an Eulerian cycle or path in a digraph.\n *  An <em>Eulerian cycle</em> is a cycle (not necessarily simple) that\n *  uses every edge in the digraph exactly once.\n *  <p>\n *  This implementation uses a nonrecursive depth-first search.\n *  The constructor takes &Theta;(<em>E</em> + <em>V</em>) time in the worst\n *  case, where <em>E</em> is the number of edges and <em>V</em> is the\n *  number of vertices\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  To compute Eulerian paths in digraphs, see {@link DirectedEulerianPath}.\n *  To compute Eulerian cycles and paths in undirected graphs, see\n *  {@link EulerianCycle} and {@link EulerianPath}.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *  @author Nate Liu\n */\npublic class DirectedEulerianCycle {\n    private Stack<Integer> cycle = null;  // Eulerian cycle; null if no such cycle\n\n    /**\n     * Computes an Eulerian cycle in the specified digraph, if one exists.\n     *\n     * @param digraph the digraph\n     */\n    public DirectedEulerianCycle(Digraph digraph) {\n\n        // must have at least one edge\n        if (digraph.E() == 0) return;\n\n        // necessary condition: indegree(v) = outdegree(v) for each vertex v\n        // (without this check, DFS might return a path instead of a cycle)\n        for (int v = 0; v < digraph.V(); v++)\n            if (digraph.outdegree(v) != digraph.indegree(v))\n                return;\n\n        // create local view of adjacency lists, to iterate one vertex at a time\n        Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            adj[v] = digraph.adj(v).iterator();\n\n        // initialize stack with any non-isolated vertex\n        int s = nonIsolatedVertex(digraph);\n        Stack<Integer> stack = new Stack<Integer>();\n        stack.push(s);\n\n        // greedily add to putative cycle, depth-first search style\n        cycle = new Stack<Integer>();\n        while (!stack.isEmpty()) {\n            int v = stack.pop();\n            while (adj[v].hasNext()) {\n                stack.push(v);\n                v = adj[v].next();\n            }\n            // add vertex with no more leaving edges to cycle\n            cycle.push(v);\n        }\n\n        // check if all edges have been used\n        // (in case there are two or more vertex-disjoint Eulerian cycles)\n        if (cycle.size() != digraph.E() + 1)\n            cycle = null;\n\n        assert certifySolution(digraph);\n    }\n\n    /**\n     * Returns the sequence of vertices on an Eulerian cycle.\n     *\n     * @return the sequence of vertices on an Eulerian cycle;\n     *         {@code null} if no such cycle\n     */\n    public Iterable<Integer> cycle() {\n        return cycle;\n    }\n\n    /**\n     * Returns true if the digraph has an Eulerian cycle.\n     *\n     * @return {@code true} if the digraph has an Eulerian cycle;\n     *         {@code false} otherwise\n     */\n    public boolean hasEulerianCycle() {\n        return cycle != null;\n    }\n\n    // returns any non-isolated vertex; -1 if no such vertex\n    private static int nonIsolatedVertex(Digraph digraph) {\n        for (int v = 0; v < digraph.V(); v++)\n            if (digraph.outdegree(v) > 0)\n                return v;\n        return -1;\n    }\n\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // Determines whether a digraph has an Eulerian cycle using necessary\n    // and sufficient conditions (without computing the cycle itself):\n    //    - at least one edge\n    //    - indegree(v) = outdegree(v) for every vertex\n    //    - the graph is connected, when viewed as an undirected graph\n    //      (ignoring isolated vertices)\n    private static boolean satisfiesNecessaryAndSufficientConditions(Digraph digraph) {\n\n        // Condition 0: at least 1 edge\n        if (digraph.E() == 0) return false;\n\n        // Condition 1: indegree(v) == outdegree(v) for every vertex\n        for (int v = 0; v < digraph.V(); v++)\n            if (digraph.outdegree(v) != digraph.indegree(v))\n                return false;\n\n        // Condition 2: graph is connected, ignoring isolated vertices\n        Graph H = new Graph(digraph.V());\n        for (int v = 0; v < digraph.V(); v++)\n            for (int w : digraph.adj(v))\n                H.addEdge(v, w);\n\n        // check that all non-isolated vertices are connected\n        int s = nonIsolatedVertex(digraph);\n        BreadthFirstPaths bfs = new BreadthFirstPaths(H, s);\n        for (int v = 0; v < digraph.V(); v++)\n            if (H.degree(v) > 0 && !bfs.hasPathTo(v))\n                return false;\n\n        return true;\n    }\n\n    // check that solution is correct\n    private boolean certifySolution(Digraph digraph) {\n\n        // internal consistency check\n        if (hasEulerianCycle() == (cycle() == null)) return false;\n\n        // hashEulerianCycle() returns correct value\n        if (hasEulerianCycle() != satisfiesNecessaryAndSufficientConditions(digraph)) return false;\n\n        // nothing else to check if no Eulerian cycle\n        if (cycle == null) return true;\n\n        // check that cycle() uses correct number of edges\n        if (cycle.size() != digraph.E() + 1) return false;\n\n        // check that cycle() is a directed cycle of G\n        // TODO\n\n        return true;\n    }\n\n\n    private static void unitTest(Digraph digraph, String description) {\n        StdOut.println(description);\n        StdOut.println(\"-------------------------------------\");\n        StdOut.print(digraph);\n\n        DirectedEulerianCycle euler = new DirectedEulerianCycle(digraph);\n\n        StdOut.print(\"Eulerian cycle: \");\n        if (euler.hasEulerianCycle()) {\n            for (int v : euler.cycle()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n        else {\n            StdOut.println(\"none\");\n        }\n        StdOut.println();\n    }\n\n\n    /**\n     * Unit tests the {@code DirectedEulerianCycle} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n\n        // Eulerian cycle\n        Digraph digraph1 = DigraphGenerator.eulerianCycle(V, E);\n        unitTest(digraph1, \"Eulerian cycle\");\n\n        // Eulerian path\n        Digraph digraph2 = DigraphGenerator.eulerianPath(V, E);\n        unitTest(digraph2, \"Eulerian path\");\n\n        // empty digraph\n        Digraph digraph3 = new Digraph(V);\n        unitTest(digraph3, \"empty digraph\");\n\n        // self loop\n        Digraph digraph4 = new Digraph(V);\n        int v4 = StdRandom.uniformInt(V);\n        digraph4.addEdge(v4, v4);\n        unitTest(digraph4, \"single self loop\");\n\n        // union of two disjoint cycles\n        Digraph H1 = DigraphGenerator.eulerianCycle(V/2, E/2);\n        Digraph H2 = DigraphGenerator.eulerianCycle(V - V/2, E - E/2);\n        int[] perm = new int[V];\n        for (int i = 0; i < V; i++)\n            perm[i] = i;\n        StdRandom.shuffle(perm);\n        Digraph digraph5 = new Digraph(V);\n        for (int v = 0; v < H1.V(); v++)\n            for (int w : H1.adj(v))\n                digraph5.addEdge(perm[v], perm[w]);\n        for (int v = 0; v < H2.V(); v++)\n            for (int w : H2.adj(v))\n                digraph5.addEdge(perm[V/2 + v], perm[V/2 + w]);\n        unitTest(digraph5, \"Union of two disjoint cycles\");\n\n        // random digraph\n        Digraph digraph6 = DigraphGenerator.simple(V, E);\n        unitTest(digraph6, \"simple digraph\");\n\n        // 4-vertex digraph\n        Digraph digraph7 = new Digraph(new In(\"eulerianD.txt\"));\n        unitTest(digraph7, \"4-vertex Eulerian digraph\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DirectedEulerianPath.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DirectedEulerianPath.java\n *  Execution:    java DirectedEulerianPath V E\n *  Dependencies: Digraph.java Stack.java StdOut.java\n *                BreadthFirstPaths.java\n *                DigraphGenerator.java StdRandom.java\n *\n *  Find an Eulerian path in a digraph, if one exists.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code DirectedEulerianPath} class represents a data type\n *  for finding an Eulerian path in a digraph.\n *  An <em>Eulerian path</em> is a path (not necessarily simple) that\n *  uses every edge in the digraph exactly once.\n *  <p>\n *  This implementation uses a nonrecursive depth-first search.\n *  The constructor take &Theta;(<em>E</em> + <em>V</em>) time\n *  in the worst case, where <em>E</em> is the number of edges and\n *  <em>V</em> is the number of vertices.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  To compute Eulerian cycles in digraphs, see {@link DirectedEulerianCycle}.\n *  To compute Eulerian cycles and paths in undirected graphs, see\n *  {@link EulerianCycle} and {@link EulerianPath}.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n * @author Robert Sedgewick\n * @author Kevin Wayne\n * @author Nate Liu\n */\npublic class DirectedEulerianPath {\n    private Stack<Integer> path = null;   // Eulerian path; null if no suh path\n\n    /**\n     * Computes an Eulerian path in the specified digraph, if one exists.\n     *\n     * @param digraph the digraph\n     */\n    public DirectedEulerianPath(Digraph digraph) {\n\n        // find vertex from which to start potential Eulerian path:\n        // a vertex v with outdegree(v) > indegree(v) if it exits;\n        // otherwise a vertex with outdegree(v) > 0\n        int deficit = 0;\n        int s = nonIsolatedVertex(digraph);\n        for (int v = 0; v < digraph.V(); v++) {\n            if (digraph.outdegree(v) > digraph.indegree(v)) {\n                deficit += (digraph.outdegree(v) - digraph.indegree(v));\n                s = v;\n            }\n        }\n\n        // digraph can't have an Eulerian path\n        // (this condition is needed)\n        if (deficit > 1) return;\n\n        // special case for digraph with zero edges (has a degenerate Eulerian path)\n        if (s == -1) s = 0;\n\n        // create local view of adjacency lists, to iterate one vertex at a time\n        Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            adj[v] = digraph.adj(v).iterator();\n\n        // greedily add to cycle, depth-first search style\n        Stack<Integer> stack = new Stack<Integer>();\n        stack.push(s);\n        path = new Stack<Integer>();\n        while (!stack.isEmpty()) {\n            int v = stack.pop();\n            while (adj[v].hasNext()) {\n                stack.push(v);\n                v = adj[v].next();\n            }\n            // push vertex with no more available edges to path\n            path.push(v);\n        }\n\n        // check if all edges have been used\n        if (path.size() != digraph.E() + 1)\n            path = null;\n\n        assert check(digraph);\n    }\n\n    /**\n     * Returns the sequence of vertices on an Eulerian path.\n     *\n     * @return the sequence of vertices on an Eulerian path;\n     *         {@code null} if no such path\n     */\n    public Iterable<Integer> path() {\n        return path;\n    }\n\n    /**\n     * Returns true if the digraph has an Eulerian path.\n     *\n     * @return {@code true} if the digraph has an Eulerian path;\n     *         {@code false} otherwise\n     */\n    public boolean hasEulerianPath() {\n        return path != null;\n    }\n\n\n    // returns any non-isolated vertex; -1 if no such vertex\n    private static int nonIsolatedVertex(Digraph digraph) {\n        for (int v = 0; v < digraph.V(); v++)\n            if (digraph.outdegree(v) > 0)\n                return v;\n        return -1;\n    }\n\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // Determines whether a digraph has an Eulerian path using necessary\n    // and sufficient conditions (without computing the path itself):\n    //    - indegree(v) = outdegree(v) for every vertex,\n    //      except one vertex v may have outdegree(v) = indegree(v) + 1\n    //      (and one vertex v may have indegree(v) = outdegree(v) + 1)\n    //    - the graph is connected, when viewed as an undirected graph\n    //      (ignoring isolated vertices)\n    private static boolean satisfiesNecessaryAndSufficientConditions(Digraph digraph) {\n        if (digraph.E() == 0) return true;\n\n        // Condition 1: indegree(v) == outdegree(v) for every vertex,\n        // except one vertex may have outdegree(v) = indegree(v) + 1\n        int deficit = 0;\n        for (int v = 0; v < digraph.V(); v++)\n            if (digraph.outdegree(v) > digraph.indegree(v))\n                deficit += (digraph.outdegree(v) - digraph.indegree(v));\n        if (deficit > 1) return false;\n\n        // Condition 2: graph is connected, ignoring isolated vertices\n        Graph H = new Graph(digraph.V());\n        for (int v = 0; v < digraph.V(); v++)\n            for (int w : digraph.adj(v))\n                H.addEdge(v, w);\n\n        // check that all non-isolated vertices are connected\n        int s = nonIsolatedVertex(digraph);\n        BreadthFirstPaths bfs = new BreadthFirstPaths(H, s);\n        for (int v = 0; v < digraph.V(); v++)\n            if (H.degree(v) > 0 && !bfs.hasPathTo(v))\n                return false;\n\n        return true;\n    }\n\n\n    private boolean check(Digraph digraph) {\n\n        // internal consistency check\n        if (hasEulerianPath() == (path() == null)) return false;\n\n        // hashEulerianPath() returns correct value\n        if (hasEulerianPath() != satisfiesNecessaryAndSufficientConditions(digraph)) return false;\n\n        // nothing else to check if no Eulerian path\n        if (path == null) return true;\n\n        // check that path() uses correct number of edges\n        if (path.size() != digraph.E() + 1) return false;\n\n        // check that path() is a directed path in G\n        // TODO\n\n        return true;\n    }\n\n\n    private static void unitTest(Digraph digraph, String description) {\n        StdOut.println(description);\n        StdOut.println(\"-------------------------------------\");\n        StdOut.print(digraph);\n\n        DirectedEulerianPath euler = new DirectedEulerianPath(digraph);\n\n        StdOut.print(\"Eulerian path:  \");\n        if (euler.hasEulerianPath()) {\n            for (int v : euler.path()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n        else {\n            StdOut.println(\"none\");\n        }\n        StdOut.println();\n    }\n\n    /**\n     * Unit tests the {@code DirectedEulerianPath} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n\n\n        // Eulerian cycle\n        Digraph digraph1 = DigraphGenerator.eulerianCycle(V, E);\n        unitTest(digraph1, \"Eulerian cycle\");\n\n        // Eulerian path\n        Digraph digraph2 = DigraphGenerator.eulerianPath(V, E);\n        unitTest(digraph2, \"Eulerian path\");\n\n        // add one random edge\n        Digraph digraph3 = new Digraph(digraph2);\n        digraph3.addEdge(StdRandom.uniformInt(V), StdRandom.uniformInt(V));\n        unitTest(digraph3, \"one random edge added to Eulerian path\");\n\n        // self loop\n        Digraph digraph4 = new Digraph(V);\n        int v4 = StdRandom.uniformInt(V);\n        digraph4.addEdge(v4, v4);\n        unitTest(digraph4, \"single self loop\");\n\n        // single edge\n        Digraph digraph5 = new Digraph(V);\n        digraph5.addEdge(StdRandom.uniformInt(V), StdRandom.uniformInt(V));\n        unitTest(digraph5, \"single edge\");\n\n        // empty digraph\n        Digraph digraph6 = new Digraph(V);\n        unitTest(digraph6, \"empty digraph\");\n\n        // random digraph\n        Digraph digraph7 = DigraphGenerator.simple(V, E);\n        unitTest(digraph7, \"simple digraph\");\n\n        // 4-vertex digraph\n        Digraph digraph8 = new Digraph(new In(\"eulerianD.txt\"));\n        unitTest(digraph8, \"4-vertex Eulerian digraph\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DoublingRatio.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DoublingRatio.java\n *  Execution:    java DoublingRatio\n *  Dependencies: ThreeSum.java Stopwatch.java StdRandom.java StdOut.java\n *\n *\n *  % java DoublingRatio\n *      250     0.0   2.7\n *      500     0.0   4.8\n *     1000     0.1   6.9\n *     2000     0.6   7.7\n *     4000     4.5   8.0\n *     8000    35.7   8.0\n *     4000     3.9   6.6\n *  ...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DoublingRatio} class provides a client for measuring\n *  the running time of a method using a doubling ratio test.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/14analysis\">Section 1.4</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DoublingRatio {\n    private static final int MAXIMUM_INTEGER = 1000000;\n\n    // This class should not be instantiated.\n    private DoublingRatio() { }\n\n    /**\n     * Returns the amount of time to call {@code ThreeSum.count()} with <em>n</em>\n     * random 6-digit integers.\n     * @param n the number of integers\n     * @return amount of time (in seconds) to call {@code ThreeSum.count()}\n     *   with <em>n</em> random 6-digit integers\n     */\n    public static double timeTrial(int n) {\n        int[] a = new int[n];\n        for (int i = 0; i < n; i++) {\n            a[i] = StdRandom.uniformInt(-MAXIMUM_INTEGER, MAXIMUM_INTEGER);\n        }\n        Stopwatch timer = new Stopwatch();\n        int ignore = ThreeSum.count(a);\n        return timer.elapsedTime();\n    }\n\n    /**\n     * Prints table of running times to call {@code ThreeSum.count()}\n     * for arrays of size 250, 500, 1000, 2000, and so forth, along\n     * with ratios of running times between successive array sizes.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        double prev = timeTrial(125);\n        for (int n = 250; true; n += n) {\n            double time = timeTrial(n);\n            StdOut.printf(\"%7d %7.1f %5.1f\\n\", n, time, time/prev);\n            prev = time;\n        }\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DoublingTest.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DoublingTest.java\n *  Execution:    java DoublingTest\n *  Dependencies: ThreeSum.java Stopwatch.java StdRandom.java StdOut.java\n *\n *  % java DoublingTest\n *      250     0.0\n *      500     0.0\n *     1000     0.1\n *     2000     0.6\n *     4000     4.5\n *     8000    35.7\n *  ...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code DoublingTest} class provides a client for measuring\n *  the running time of a method using a doubling test.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/14analysis\">Section 1.4</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class DoublingTest {\n    private static final int MAXIMUM_INTEGER = 1000000;\n\n    // This class should not be instantiated.\n    private DoublingTest() { }\n\n    /**\n     * Returns the amount of time to call {@code ThreeSum.count()} with <em>n</em>\n     * random 6-digit integers.\n     * @param n the number of integers\n     * @return amount of time (in seconds) to call {@code ThreeSum.count()}\n     *   with <em>n</em> random 6-digit integers\n     */\n    public static double timeTrial(int n) {\n        int[] a = new int[n];\n        for (int i = 0; i < n; i++) {\n            a[i] = StdRandom.uniformInt(-MAXIMUM_INTEGER, MAXIMUM_INTEGER);\n        }\n        Stopwatch timer = new Stopwatch();\n        int ignore = ThreeSum.count(a);\n        return timer.elapsedTime();\n    }\n\n    /**\n     * Prints table of running times to call {@code ThreeSum.count()}\n     * for arrays of size 250, 500, 1000, 2000, and so forth.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        for (int n = 250; true; n += n) {\n            double time = timeTrial(n);\n            StdOut.printf(\"%7d %7.1f\\n\", n, time);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Draw.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Draw.java\n *  Execution:    java Draw\n *  Dependencies: none\n *\n *  Drawing library. This class provides a basic capability for creating\n *  drawings with your programs. It uses a simple graphics model that\n *  allows you to create drawings consisting of points, lines, and curves\n *  in a window on your computer and to save the drawings to a file.\n *  This is the object-oriented version of standard draw; it supports\n *  multiple independent drawing windows.\n *\n *  Todo\n *  ----\n *    -  Add support for gradient fill, etc.\n *\n *  Remarks\n *  -------\n *    -  don't use AffineTransform for rescaling since it inverts\n *       images and strings\n *    -  careful using setFont in inner loop within an animation -\n *       it can cause flicker\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.BasicStroke;\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.FileDialog;\nimport java.awt.Font;\nimport java.awt.FontMetrics;\nimport java.awt.Graphics;\nimport java.awt.Graphics2D;\nimport java.awt.Image;\nimport java.awt.MediaTracker;\nimport java.awt.RenderingHints;\nimport java.awt.Toolkit;\n\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.awt.event.MouseEvent;\nimport java.awt.event.MouseListener;\nimport java.awt.event.MouseMotionListener;\nimport java.awt.event.KeyEvent;\nimport java.awt.event.KeyListener;\n\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport java.awt.geom.Arc2D;\nimport java.awt.geom.Ellipse2D;\nimport java.awt.geom.GeneralPath;\nimport java.awt.geom.Line2D;\nimport java.awt.geom.Rectangle2D;\n\nimport java.awt.image.BufferedImage;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.net.URI;\nimport java.net.URISyntaxException;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.TreeSet;\n\nimport javax.imageio.ImageIO;\n\nimport javax.swing.ImageIcon;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.KeyStroke;\n\n/**\n *  The <code>Draw</code> data type provides a basic capability for\n *  creating drawings with your programs. It uses a simple graphics model that\n *  allows you to create drawings consisting of points, lines, and curves\n *  in a window on your computer and to save the drawings to a file.\n *  This is the object-oriented version of standard draw; it supports\n *  multiple independent drawing windows.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class Draw implements ActionListener, MouseListener, MouseMotionListener, KeyListener {\n\n    /**\n     *  The color aqua (0, 255, 255).\n     */\n    public static final Color AQUA = new Color(0, 255, 255);\n\n    /**\n     *  The color black (0, 0, 0).\n     */\n    public static final Color BLACK = Color.BLACK;\n\n    /**\n     *  The color blue (0, 0, 255).\n     */\n    public static final Color BLUE = Color.BLUE;\n\n    /**\n     *  The color cyan (0, 255, 255).\n     */\n    public static final Color CYAN = Color.CYAN;\n\n    /**\n     *  The color fuscia (255, 0, 255).\n     */\n    public static final Color FUSCIA = new Color(255, 0, 255);\n\n    /**\n     *  The color dark gray (64, 64, 64).\n     */\n    public static final Color DARK_GRAY = Color.DARK_GRAY;\n\n    /**\n     *  The color gray (128, 128, 128).\n     */\n    public static final Color GRAY = Color.GRAY;\n\n    /**\n     *  The color green (0, 128, 0).\n     */\n    public static final Color GREEN = new Color(0, 128, 0);\n\n    /**\n     *  The color light gray (192, 192, 192).\n     */\n    public static final Color LIGHT_GRAY = Color.LIGHT_GRAY;\n\n    /**\n     *  The color lime (0, 255, 0).\n     */\n    public static final Color LIME = new Color(0, 255, 0);\n\n    /**\n     *  The color magenta (255, 0, 255).\n     */\n    public static final Color MAGENTA = Color.MAGENTA;\n\n    /**\n     *  The color maroon (128, 0, 0).\n     */\n    public static final Color MAROON = new Color(128, 0, 0);\n\n    /**\n     *  The color navy (0, 0, 128).\n     */\n    public static final Color NAVY = new Color(0, 0, 128);\n\n    /**\n     *  The color olive (128, 128, 0).\n     */\n    public static final Color OLIVE = new Color(128, 128, 0);\n\n    /**\n     *  The color orange (255, 200, 0).\n     */\n    public static final Color ORANGE = Color.ORANGE;\n\n    /**\n     *  The color pink (255, 175, 175).\n     */\n    public static final Color PINK = Color.PINK;\n\n    /**\n     *  The color purple (128, 0, 128).\n     */\n    public static final Color PURPLE = new Color(128, 0, 128);\n\n    /**\n     *  The color red (255, 0, 0).\n     */\n    public static final Color RED = Color.RED;\n\n    /**\n     *  The color silver (192, 192, 192).\n     */\n    public static final Color SILVER = new Color(192, 192, 192);\n\n    /**\n     *  The color teal (0, 128, 128).\n     */\n    public static final Color TEAL = new Color(0, 128, 128);\n\n    /**\n     *  The color white (255, 255, 255).\n     */\n    public static final Color WHITE = Color.WHITE;\n\n    /**\n     *  The color yellow (255, 255, 0).\n     */\n    public static final Color YELLOW = Color.YELLOW;\n\n    /**\n     *  A 100% transparent color, for a transparent background.\n     */\n    public static final Color TRANSPARENT = new Color(0, 0, 0, 0);\n\n    /**\n     * The shade of blue used in <em>Introduction to Programming in Java</em>.\n     * It is Pantone 300U. The RGB values are approximately (9, 90, 166).\n     */\n    public static final Color BOOK_BLUE = new Color(9, 90, 166);\n\n    /**\n     * The shade of light blue used in <em>Introduction to Programming in Java</em>.\n     * The RGB values are approximately (103, 198, 243).\n     */\n    public static final Color BOOK_LIGHT_BLUE = new Color(103, 198, 243);\n\n    /**\n     * The shade of red used in <em>Algorithms, 4th edition</em>.\n     * It is Pantone 1805U. The RGB values are approximately (150, 35, 31).\n     */\n    public static final Color BOOK_RED = new Color(150, 35, 31);\n\n    /**\n     * The shade of orange used in Princeton University's identity.\n     * It is PMS 158. The RGB values are approximately (245, 128, 37).\n     */\n    public static final Color PRINCETON_ORANGE = new Color(245, 128, 37);\n\n    // default colors\n    private static final Color DEFAULT_PEN_COLOR = BLACK;\n    private static final Color DEFAULT_BACKGROUND_COLOR = WHITE;\n\n\n    // boundary of drawing canvas, 0% border\n    private static final double BORDER = 0.0;\n    private static final double DEFAULT_XMIN = 0.0;\n    private static final double DEFAULT_XMAX = 1.0;\n    private static final double DEFAULT_YMIN = 0.0;\n    private static final double DEFAULT_YMAX = 1.0;\n\n    // default canvas size is SIZE-by-SIZE\n    private static final int DEFAULT_SIZE = 512;\n\n    // default pen radius\n    private static final double DEFAULT_PEN_RADIUS = 0.002;\n\n    // default font\n    private static final Font DEFAULT_FONT = new Font(\"SansSerif\", Font.PLAIN, 16);\n\n    // default title of drawing window\n    private static final String DEFAULT_WINDOW_TITLE = \"Draw\";\n\n    // current pen color\n    private Color penColor = DEFAULT_PEN_COLOR;\n\n    // background color\n    private Color backgroundColor = DEFAULT_BACKGROUND_COLOR;\n\n    // current title of drawing window\n    private String windowTitle = DEFAULT_WINDOW_TITLE;\n\n    // canvas size\n    private int width  = DEFAULT_SIZE;\n    private int height = DEFAULT_SIZE;\n\n    // current pen radius\n    private double penRadius = DEFAULT_PEN_RADIUS;\n\n    // show we draw immediately or wait until next show?\n    private boolean defer = false;\n\n    private double xmin = DEFAULT_XMIN;\n    private double xmax = DEFAULT_XMAX;\n    private double ymin = DEFAULT_YMIN;\n    private double ymax = DEFAULT_YMAX;\n\n    // for synchronization\n    private final Object mouseLock = new Object();\n    private final Object keyLock = new Object();\n\n    // current font\n    private Font font = DEFAULT_FONT;\n\n    // the JLabel for drawing\n    private JLabel draw;\n\n    // double buffered graphics\n    private BufferedImage offscreenImage, onscreenImage;\n    private Graphics2D offscreen, onscreen;\n\n    // the frame for drawing to the screen\n    private JFrame frame;\n\n    // is the JFrame visible (upon calling draw())?\n    private static boolean isJFrameVisible = true;\n\n    // mouse state\n    private boolean isMousePressed = false;\n    private double mouseX = 0;\n    private double mouseY = 0;\n\n    // keyboard state\n    private final LinkedList<Character> keysTyped = new LinkedList<Character>();\n    private final TreeSet<Integer> keysDown = new TreeSet<Integer>();\n\n    // event-based listeners\n    private final ArrayList<DrawListener> listeners = new ArrayList<DrawListener>();\n\n    // timer\n    private Timer timer;\n\n    /**\n     * Initializes an empty drawing object.\n     */\n    public Draw() {\n        initCanvas();\n        initGUI();\n    }\n\n    // initialize the drawing canvas\n    private void initCanvas() {\n\n        // BufferedImage stuff\n        offscreenImage = new BufferedImage(2*width, 2*height, BufferedImage.TYPE_INT_ARGB);\n        onscreenImage  = new BufferedImage(2*width, 2*height, BufferedImage.TYPE_INT_ARGB);\n        offscreen = offscreenImage.createGraphics();\n        onscreen  = onscreenImage.createGraphics();\n        offscreen.scale(2.0, 2.0);  // since we made it 2x as big\n\n        // initialize drawing window\n        offscreen.setBackground(DEFAULT_BACKGROUND_COLOR);\n        offscreen.clearRect(0, 0, width, height);\n        onscreen.setBackground(DEFAULT_BACKGROUND_COLOR);\n        onscreen.clearRect(0, 0, 2*width, 2*height);\n\n        // set the pen color\n        offscreen.setColor(penColor);\n\n        // add antialiasing\n        RenderingHints hints = new RenderingHints(null);\n        hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\n        hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\n        offscreen.addRenderingHints(hints);\n    }\n\n    // initialize the GUI\n    private void initGUI() {\n\n        // create the JFrame (if necessary)\n        if (frame == null) {\n            frame = new JFrame();\n            frame.addKeyListener(this);    // JLabel cannot get keyboard focus\n            frame.setFocusTraversalKeysEnabled(false);  // allow VK_TAB with isKeyPressed()\n            frame.setResizable(false);\n            // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            // closes all windows\n            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);      // closes only current window\n            frame.setTitle(windowTitle);\n            frame.setJMenuBar(createMenuBar());\n        }\n\n        // create the ImageIcon\n        RetinaImageIcon icon = new RetinaImageIcon(onscreenImage);\n        draw = new JLabel(icon);\n        draw.addMouseListener(this);\n        draw.addMouseMotionListener(this);\n\n        // finish up the JFrame\n        frame.setContentPane(draw);\n        frame.pack();\n        frame.requestFocusInWindow();\n        frame.setVisible(false);\n    }\n\n\n    /**\n     * Makes the drawing window visible or invisible.\n     *\n     * @param  isVisible if {@code true}, makes the drawing window visible,\n     *         otherwise hides the drawing window.\n     */\n    public void setVisible(boolean isVisible) {\n        isJFrameVisible = isVisible;\n        frame.setVisible(isVisible);\n    }\n\n    /**\n     * Sets the upper-left hand corner of the drawing window to be (x, y),\n     * where (0, 0) is upper left.\n     *\n     * @param  x the number of pixels from the left\n     * @param  y the number of pixels from the top\n     * @throws IllegalArgumentException if the width or height is 0 or negative\n     */\n    public void setLocationOnScreen(int x, int y) {\n        if (x <= 0 || y <= 0) throw new IllegalArgumentException();\n        frame.setLocation(x, y);\n    }\n\n    /**\n     * Sets the default close operation.\n     *\n     * @param  value the value, typically {@code JFrame.EXIT_ON_CLOSE}\n     *         (close all windows) or {@code JFrame.DISPOSE_ON_CLOSE}\n     *         (close current window)\n     */\n    public void setDefaultCloseOperation(int value) {\n        frame.setDefaultCloseOperation(value);\n    }\n\n    /**\n     * Sets the canvas (drawing area) to be 512-by-512 pixels.\n     * This also clears the current drawing using the default background color (white).\n     * Ordinarily, this method is called once, at the very beginning of a program.\n     */\n    public void setCanvasSize() {\n        setCanvasSize(DEFAULT_SIZE, DEFAULT_SIZE);\n    }\n\n    /**\n     * Sets the canvas (drawing area) to be <em>width</em>-by-<em>height</em> pixels.\n     * This also clears the current drawing using the default background color (white).\n     * Ordinarily, this method is called once, at the very beginning of a program.\n     *\n     * @param  canvasWidth the width as a number of pixels\n     * @param  canvasHeight the height as a number of pixels\n     * @throws IllegalArgumentException unless both {@code canvasWidth}\n     *         and {@code canvasHeight} are positive\n     */\n    public void setCanvasSize(int canvasWidth, int canvasHeight) {\n        if (canvasWidth < 1 || canvasHeight < 1) {\n            throw new IllegalArgumentException(\"width and height must be positive\");\n        }\n        width = canvasWidth;\n        height = canvasHeight;\n        initCanvas();\n        initGUI();\n    }\n\n\n    // create the menu bar\n    private JMenuBar createMenuBar() {\n        JMenuBar menuBar = new JMenuBar();\n        JMenu menu = new JMenu(\"File\");\n        menuBar.add(menu);\n        JMenuItem menuItem1 = new JMenuItem(\" Save...   \");\n        menuItem1.addActionListener(this);\n        // Java 11: use getMenuShortcutKeyMaskEx()\n        // Java 8:  use getMenuShortcutKeyMask()\n        menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,\n                                Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));\n        menu.add(menuItem1);\n        return menuBar;\n    }\n\n    /**\n     * Closes the drawing window.\n     * This allows the client program to terminate instead of requiring\n     * the user to close the drawing window manually.\n     * Drawing after calling this method will restore the previous window state.\n     */\n    public void close() {\n        frame.dispose();\n    }\n\n   /***************************************************************************\n    *  Input validation helper methods.\n    ***************************************************************************/\n\n    // throw an IllegalArgumentException if x is NaN or infinite\n    private static void validate(double x, String name) {\n        if (Double.isNaN(x)) throw new IllegalArgumentException(name + \" is NaN\");\n        if (Double.isInfinite(x)) throw new IllegalArgumentException(name + \" is infinite\");\n    }\n\n    // throw an IllegalArgumentException if s is null\n    private static void validateNonnegative(double x, String name) {\n        if (x < 0) throw new IllegalArgumentException(name + \" negative\");\n    }\n\n    // throw an IllegalArgumentException if s is null\n    private static void validateNotNull(Object x, String name) {\n        if (x == null) throw new IllegalArgumentException(name + \" is null\");\n    }\n\n\n   /***************************************************************************\n    *  Set the title of the drawing window.\n    ***************************************************************************/\n\n    /**\n     * Sets the title of the drawing window to the specified string.\n     *\n     * @param  windowTitle the title of the window\n     * @throws IllegalArgumentException if {@code title} is {@code null}\n     */\n    public void setTitle(String windowTitle) {\n        validateNotNull(windowTitle, \"title\");\n        this.windowTitle = windowTitle;\n        frame.setTitle(windowTitle);\n    }\n\n   /***************************************************************************\n    *  User and screen coordinate systems.\n    ***************************************************************************/\n\n    /**\n     * Sets the x-scale to the default range (between 0.0 and 1.0).\n     */\n    public void setXscale() {\n        setXscale(DEFAULT_XMIN, DEFAULT_XMAX);\n    }\n\n    /**\n     * Sets the y-scale to the default range (between 0.0 and 1.0).\n     */\n    public void setYscale() {\n        setYscale(DEFAULT_YMIN, DEFAULT_YMAX);\n    }\n\n    /**\n     * Sets the x-scale to the specified range.\n     *\n     * @param min the minimum value of the x-scale\n     * @param max the maximum value of the x-scale\n     * @throws IllegalArgumentException if {@code (max == min)}\n     * @throws IllegalArgumentException if either {@code min} or {@code max} is either NaN or infinite\n     */\n    public void setXscale(double min, double max) {\n        validate(min, \"min\");\n        validate(max, \"max\");\n        double size = max - min;\n        if (size == 0.0) throw new IllegalArgumentException(\"the min and max are the same\");\n        xmin = min - BORDER * size;\n        xmax = max + BORDER * size;\n    }\n\n    /**\n     * Sets the y-scale to the specified range.\n     *\n     * @param min the minimum value of the y-scale\n     * @param max the maximum value of the y-scale\n     * @throws IllegalArgumentException if {@code (max == min)}\n     * @throws IllegalArgumentException if either {@code min} or {@code max} is either NaN or infinite\n     */\n    public void setYscale(double min, double max) {\n        validate(min, \"min\");\n        validate(max, \"max\");\n        double size = max - min;\n        if (size == 0.0) throw new IllegalArgumentException(\"the min and max are the same\");\n        ymin = min - BORDER * size;\n        ymax = max + BORDER * size;\n    }\n\n    /**\n     * Sets both the x-scale and y-scale to the default range (between 0.0 and 1.0).\n     */\n    public void setScale() {\n        setXscale();\n        setYscale();\n    }\n\n    /**\n     * Sets both the x-scale and y-scale to the (same) specified range.\n     * @param min the minimum value of the y-scale\n     * @param max the maximum value of the y-scale\n     * @throws IllegalArgumentException if {@code (max == min)}\n     * @throws IllegalArgumentException if either {@code min} or {@code max} is either NaN or infinite\n     */\n    public void setScale(double min, double max) {\n        setXscale(min, max);\n        setYscale(min, max);\n    }\n\n\n    // helper functions that scale from user coordinates to screen coordinates and back\n    private double  scaleX(double x) { return width  * (x - xmin) / (xmax - xmin); }\n    private double  scaleY(double y) { return height * (ymax - y) / (ymax - ymin); }\n    private double factorX(double w) { return w * width  / Math.abs(xmax - xmin);  }\n    private double factorY(double h) { return h * height / Math.abs(ymax - ymin);  }\n    private double   userX(double x) { return xmin + x * (xmax - xmin) / width;    }\n    private double   userY(double y) { return ymax - y * (ymax - ymin) / height;   }\n\n\n    /**\n     * Clears the screen using the default background color (white).\n     */\n    public void clear() {\n        clear(DEFAULT_BACKGROUND_COLOR);\n    }\n\n    /**\n     * Clears the screen using the specified background color.\n     * To make the background transparent, use {@code Draw.TRANSPARENT}.\n     *\n     * @param color the color to make the background\n     * @throws IllegalArgumentException if {@code color} is {@code null}\n     */\n    public void clear(Color color) {\n        validateNotNull(color, \"color\");\n\n        backgroundColor = color;\n        offscreen.setBackground(backgroundColor);\n        offscreen.clearRect(0, 0, width, height);\n\n        draw();\n    }\n\n    /**\n     * Returns the current pen radius.\n     *\n     * @return the current pen radius\n     */\n    public double getPenRadius() {\n        return penRadius;\n    }\n\n    /**\n     * Sets the pen radius to the default (0.002).\n     */\n    public void setPenRadius() {\n        setPenRadius(DEFAULT_PEN_RADIUS);\n    }\n\n    /**\n     * Sets the radius of the pen to the given size.\n     *\n     * @param  radius the radius of the pen\n     * @throws IllegalArgumentException if {@code radius} is negative, NaN, or infinite\n     */\n    public void setPenRadius(double radius) {\n        validate(radius, \"pen radius\");\n        validateNonnegative(radius, \"pen radius\");\n\n        penRadius = radius * DEFAULT_SIZE;\n        BasicStroke stroke = new BasicStroke((float) penRadius, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);\n        // BasicStroke stroke = new BasicStroke((float) penRadius);\n        offscreen.setStroke(stroke);\n    }\n\n    /**\n     * Returns the current pen color.\n     *\n     * @return the current pen color\n     */\n    public Color getPenColor() {\n        return penColor;\n    }\n\n    /**\n     * Returns the current background color.\n     *\n     * @return the current background color\n     */\n    public Color getBackgroundColor() {\n        return backgroundColor;\n    }\n\n    /**\n     * Sets the pen color to the default color (black).\n     */\n    public void setPenColor() {\n        setPenColor(DEFAULT_PEN_COLOR);\n    }\n\n    /**\n     * Sets the pen color to the given color.\n     *\n     * @param color the color to make the pen\n     * @throws IllegalArgumentException if {@code color} is {@code null}\n     */\n    public void setPenColor(Color color) {\n        validateNotNull(color, \"color\");\n        penColor = color;\n        offscreen.setColor(penColor);\n    }\n\n    /**\n     * Sets the pen color to the given RGB color.\n     *\n     * @param  red the amount of red (between 0 and 255)\n     * @param  green the amount of green (between 0 and 255)\n     * @param  blue the amount of blue (between 0 and 255)\n     * @throws IllegalArgumentException if {@code red}, {@code green},\n     *         or {@code blue} is outside its prescribed range\n     */\n    public void setPenColor(int red, int green, int blue) {\n        if (red   < 0 || red   >= 256) throw new IllegalArgumentException(\"red must be between 0 and 255\");\n        if (green < 0 || green >= 256) throw new IllegalArgumentException(\"green must be between 0 and 255\");\n        if (blue  < 0 || blue  >= 256) throw new IllegalArgumentException(\"blue must be between 0 and 255\");\n        setPenColor(new Color(red, green, blue));\n    }\n\n\n    /**\n     * Turns on xor mode.\n     */\n    public void xorOn() {\n        offscreen.setXORMode(backgroundColor);\n    }\n\n    /**\n     * Turns off xor mode.\n     */\n    public void xorOff() {\n        offscreen.setPaintMode();\n    }\n\n    /**\n     * Returns the current {@code JLabel} for use in some other GUI.\n     *\n     * @return the current {@code JLabel}\n     */\n    public JLabel getJLabel() {\n        return draw;\n    }\n\n    /**\n     * Returns the current font.\n     *\n     * @return the current font\n     */\n    public Font getFont() {\n        return font;\n    }\n\n    /**\n     * Sets the font to the default font (sans serif, 16 point).\n     */\n    public void setFont() {\n        setFont(DEFAULT_FONT);\n    }\n\n    /**\n     * Sets the font to the given value.\n     *\n     * @param font the font\n     * @throws IllegalArgumentException if {@code font} is {@code null}\n     */\n    public void setFont(Font font) {\n        validateNotNull(font, \"font\");\n        this.font = font;\n    }\n\n\n   /***************************************************************************\n    *  Drawing geometric shapes.\n    ***************************************************************************/\n\n    /**\n     * Draws a line from (x0, y0) to (x1, y1).\n     *\n     * @param x0 the x-coordinate of the starting point\n     * @param y0 the y-coordinate of the starting point\n     * @param x1 the x-coordinate of the destination point\n     * @param y1 the y-coordinate of the destination point\n     * @throws IllegalArgumentException if any coordinate is either NaN or infinite\n     */\n    public void line(double x0, double y0, double x1, double y1) {\n        validate(x0, \"x0\");\n        validate(y0, \"y0\");\n        validate(x1, \"x1\");\n        validate(y1, \"y1\");\n        offscreen.draw(new Line2D.Double(scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1)));\n        draw();\n    }\n\n    /**\n     * Draws one pixel at (x, y).\n     *\n     * @param x the x-coordinate of the pixel\n     * @param y the y-coordinate of the pixel\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    private void pixel(double x, double y) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        offscreen.fillRect((int) Math.round(scaleX(x)), (int) Math.round(scaleY(y)), 1, 1);\n    }\n\n    /**\n     * Draws a point at (x, y).\n     *\n     * @param x the x-coordinate of the point\n     * @param y the y-coordinate of the point\n     * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite\n     */\n    public void point(double x, double y) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double r = penRadius;\n        // double ws = factorX(2*r);\n        // double hs = factorY(2*r);\n        // if (ws <= 1 && hs <= 1) pixel(x, y);\n        if (r <= 1) pixel(x, y);\n        else offscreen.fill(new Ellipse2D.Double(xs - r/2, ys - r/2, r, r));\n        draw();\n    }\n\n    /**\n     * Draws a circle of the specified radius, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the x-coordinate of the center of the circle\n     * @param  y the y-coordinate of the center of the circle\n     * @param  radius the radius of the circle\n     * @throws IllegalArgumentException if {@code radius} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void circle(double x, double y, double radius) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(radius, \"radius\");\n        validateNonnegative(radius, \"radius\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*radius);\n        double hs = factorY(2*radius);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled circle of the specified radius, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the x-coordinate of the center of the circle\n     * @param  y the y-coordinate of the center of the circle\n     * @param  radius the radius of the circle\n     * @throws IllegalArgumentException if {@code radius} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void filledCircle(double x, double y, double radius) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(radius, \"radius\");\n        validateNonnegative(radius, \"radius\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*radius);\n        double hs = factorY(2*radius);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n\n    /**\n     * Draws an ellipse with the specified semimajor and semiminor axes,\n     * centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the ellipse\n     * @param  y the <em>y</em>-coordinate of the center of the ellipse\n     * @param  semiMajorAxis is the semimajor axis of the ellipse\n     * @param  semiMinorAxis is the semiminor axis of the ellipse\n     * @throws IllegalArgumentException if either {@code semiMajorAxis}\n     *         or {@code semiMinorAxis} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(semiMajorAxis, \"semimajor axis\");\n        validate(semiMinorAxis, \"semiminor axis\");\n        validateNonnegative(semiMajorAxis, \"semimajor axis\");\n        validateNonnegative(semiMinorAxis, \"semiminor axis\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*semiMajorAxis);\n        double hs = factorY(2*semiMinorAxis);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled ellipse with the specified semimajor and semiminor axes,\n     * centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the ellipse\n     * @param  y the <em>y</em>-coordinate of the center of the ellipse\n     * @param  semiMajorAxis is the semimajor axis of the ellipse\n     * @param  semiMinorAxis is the semiminor axis of the ellipse\n     * @throws IllegalArgumentException if either {@code semiMajorAxis}\n     *         or {@code semiMinorAxis} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(semiMajorAxis, \"semimajor axis\");\n        validate(semiMinorAxis, \"semiminor axis\");\n        validateNonnegative(semiMajorAxis, \"semimajor axis\");\n        validateNonnegative(semiMinorAxis, \"semiminor axis\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*semiMajorAxis);\n        double hs = factorY(2*semiMinorAxis);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a circular arc of the specified radius,\n     * centered at (<em>x</em>, <em>y</em>), from angle1 to angle2 (in degrees).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the circle\n     * @param  y the <em>y</em>-coordinate of the center of the circle\n     * @param  radius the radius of the circle\n     * @param  angle1 the starting angle. 0 would mean an arc beginning at 3 o'clock.\n     * @param  angle2 the angle at the end of the arc. For example, if\n     *         you want a 90 degree arc, then angle2 should be angle1 + 90.\n     * @throws IllegalArgumentException if {@code radius} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void arc(double x, double y, double radius, double angle1, double angle2) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(radius, \"arc radius\");\n        validate(angle1, \"angle1\");\n        validate(angle2, \"angle2\");\n        validateNonnegative(radius, \"arc radius\");\n\n        while (angle2 < angle1) angle2 += 360;\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*radius);\n        double hs = factorY(2*radius);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Arc2D.Double(xs - ws/2, ys - hs/2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN));\n        draw();\n    }\n\n    /**\n     * Draws a square of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the square\n     * @param  y the <em>y</em>-coordinate of the center of the square\n     * @param  halfLength one half the length of any side of the square\n     * @throws IllegalArgumentException if {@code halfLength} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void square(double x, double y, double halfLength) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfLength, \"halfLength\");\n        validateNonnegative(halfLength, \"half length\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfLength);\n        double hs = factorY(2*halfLength);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a square of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the square\n     * @param  y the <em>y</em>-coordinate of the center of the square\n     * @param  halfLength one half the length of any side of the square\n     * @throws IllegalArgumentException if {@code halfLength} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void filledSquare(double x, double y, double halfLength) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfLength, \"halfLength\");\n        validateNonnegative(halfLength, \"half length\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfLength);\n        double hs = factorY(2*halfLength);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n\n    /**\n     * Draws a rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the rectangle\n     * @param  y the <em>y</em>-coordinate of the center of the rectangle\n     * @param  halfWidth one half the width of the rectangle\n     * @param  halfHeight one half the height of the rectangle\n     * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void rectangle(double x, double y, double halfWidth, double halfHeight) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfWidth, \"halfWidth\");\n        validate(halfHeight, \"halfHeight\");\n        validateNonnegative(halfWidth, \"half width\");\n        validateNonnegative(halfHeight, \"half height\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfWidth);\n        double hs = factorY(2*halfHeight);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the rectangle\n     * @param  y the <em>y</em>-coordinate of the center of the rectangle\n     * @param  halfWidth one half the width of the rectangle\n     * @param  halfHeight one half the height of the rectangle\n     * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public void filledRectangle(double x, double y, double halfWidth, double halfHeight) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfWidth, \"halfWidth\");\n        validate(halfHeight, \"halfHeight\");\n        validateNonnegative(halfWidth, \"half width\");\n        validateNonnegative(halfHeight, \"half height\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfWidth);\n        double hs = factorY(2*halfHeight);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a polygon with the vertices\n     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),\n     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,\n     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).\n     *\n     * @param  x an array of all the <em>x</em>-coordinates of the polygon\n     * @param  y an array of all the <em>y</em>-coordinates of the polygon\n     * @throws IllegalArgumentException unless {@code x[]} and {@code y[]}\n     *         are of the same length\n     * @throws IllegalArgumentException if any coordinate is either NaN or infinite\n     * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null}\n     */\n    public void polygon(double[] x, double[] y) {\n        validateNotNull(x, \"x-coordinate array\");\n        validateNotNull(y, \"y-coordinate array\");\n        for (int i = 0; i < x.length; i++) validate(x[i], \"x[\" + i + \"]\");\n        for (int i = 0; i < y.length; i++) validate(y[i], \"y[\" + i + \"]\");\n\n        int n1 = x.length;\n        int n2 = y.length;\n        if (n1 != n2) throw new IllegalArgumentException(\"arrays must be of the same length\");\n        int n = n1;\n        if (n == 0) return;\n\n        GeneralPath path = new GeneralPath();\n        path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0]));\n        for (int i = 0; i < n; i++)\n            path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i]));\n        path.closePath();\n        offscreen.draw(path);\n        draw();\n    }\n\n    /**\n     * Draws a filled polygon with the vertices\n     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),\n     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,\n     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).\n     *\n     * @param  x an array of all the <em>x</em>-coordinates of the polygon\n     * @param  y an array of all the <em>y</em>-coordinates of the polygon\n     * @throws IllegalArgumentException unless {@code x[]} and {@code y[]}\n     *         are of the same length\n     * @throws IllegalArgumentException if any coordinate is either NaN or infinite\n     * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null}\n     */\n    public void filledPolygon(double[] x, double[] y) {\n        validateNotNull(x, \"x-coordinate array\");\n        validateNotNull(y, \"y-coordinate array\");\n        for (int i = 0; i < x.length; i++) validate(x[i], \"x[\" + i + \"]\");\n        for (int i = 0; i < y.length; i++) validate(y[i], \"y[\" + i + \"]\");\n\n        int n1 = x.length;\n        int n2 = y.length;\n        if (n1 != n2) throw new IllegalArgumentException(\"arrays must be of the same length\");\n        int n = n1;\n        if (n == 0) return;\n\n        GeneralPath path = new GeneralPath();\n        path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0]));\n        for (int i = 0; i < n; i++)\n            path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i]));\n        path.closePath();\n        offscreen.fill(path);\n        draw();\n    }\n\n\n\n   /***************************************************************************\n    *  Drawing images.\n    ***************************************************************************/\n\n    // get an image from the given filename\n    private static Image getImage(String filename) {\n        if (filename == null) throw new IllegalArgumentException();\n\n        // to read from file\n        ImageIcon icon = new ImageIcon(filename);\n\n        // try to read from URL\n        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {\n            try {\n                URI uri = new URI(filename);\n                if (uri.isAbsolute()) {\n                    URL url = uri.toURL();\n                    icon = new ImageIcon(url);\n                }\n            }\n            catch (MalformedURLException | URISyntaxException e) {\n                /* not a url */\n            }\n        }\n\n        // in case file is inside a .jar (classpath relative to Draw)\n        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {\n            URL url = Draw.class.getResource(filename);\n            if (url != null)\n                icon = new ImageIcon(url);\n        }\n\n        // in case file is inside a .jar (classpath relative to root of jar)\n        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {\n            URL url = Draw.class.getResource(\"/\" + filename);\n            if (url == null) throw new IllegalArgumentException(\"could not read image: '\" + filename + \"'\");\n            icon = new ImageIcon(url);\n        }\n\n        return icon.getImage();\n    }\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>).\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     * As an optimization, the picture is cached, so there is no performance\n     * penalty for redrawing the same image multiple times (e.g., in an animation).\n     * However, if you change the picture file after drawing it, subsequent\n     * calls will draw the original picture.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @throws IllegalArgumentException if the image filename is invalid\n     * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite\n     */\n    public void picture(double x, double y, String filename) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(filename, \"filename\");\n\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int ws = image.getWidth(null);\n        int hs = image.getHeight(null);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n\n        offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null);\n        draw();\n    }\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>),\n     * rotated given number of degrees.\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @param  degrees is the number of degrees to rotate counterclockwise\n     * @throws IllegalArgumentException if the image filename is invalid\n     * @throws IllegalArgumentException if {@code x}, {@code y}, {@code degrees} is NaN or infinite\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public void picture(double x, double y, String filename, double degrees) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(degrees, \"degrees\");\n        validateNotNull(filename, \"filename\");\n\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int ws = image.getWidth(null);\n        int hs = image.getHeight(null);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n\n        offscreen.rotate(Math.toRadians(-degrees), xs, ys);\n        offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null);\n        offscreen.rotate(Math.toRadians(+degrees), xs, ys);\n\n        draw();\n    }\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>),\n     * rescaled to the specified bounding box.\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @param  scaledWidth the width of the scaled image (in screen coordinates)\n     * @param  scaledHeight the height of the scaled image (in screen coordinates)\n     * @throws IllegalArgumentException if either {@code scaledWidth}\n     *         or {@code scaledHeight} is negative\n     * @throws IllegalArgumentException if the image filename is invalid\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(scaledWidth, \"scaled width\");\n        validate(scaledHeight, \"scaled height\");\n        validateNotNull(filename, \"filename\");\n        validateNonnegative(scaledWidth, \"scaled width\");\n        validateNonnegative(scaledHeight, \"scaled height\");\n\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(scaledWidth);\n        double hs = factorY(scaledHeight);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else {\n            offscreen.drawImage(image, (int) Math.round(xs - ws/2.0),\n                                       (int) Math.round(ys - hs/2.0),\n                                       (int) Math.round(ws),\n                                       (int) Math.round(hs), null);\n        }\n        draw();\n    }\n\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>), rotated\n     * given number of degrees, and rescaled to the specified bounding box.\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @param  scaledWidth the width of the scaled image (in screen coordinates)\n     * @param  scaledHeight the height of the scaled image (in screen coordinates)\n     * @param  degrees is the number of degrees to rotate counterclockwise\n     * @throws IllegalArgumentException if either {@code scaledWidth}\n     *         or {@code scaledHeight} is negative\n     * @throws IllegalArgumentException if the image filename is invalid\n     */\n    public void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(scaledWidth, \"scaled width\");\n        validate(scaledHeight, \"scaled height\");\n        validate(degrees, \"degrees\");\n        validateNotNull(filename, \"filename\");\n        validateNonnegative(scaledWidth, \"scaled width\");\n        validateNonnegative(scaledHeight, \"scaled height\");\n\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(scaledWidth);\n        double hs = factorY(scaledHeight);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n\n        offscreen.rotate(Math.toRadians(-degrees), xs, ys);\n        offscreen.drawImage(image, (int) Math.round(xs - ws/2.0),\n                                   (int) Math.round(ys - hs/2.0),\n                                   (int) Math.round(ws),\n                                   (int) Math.round(hs), null);\n        offscreen.rotate(Math.toRadians(+degrees), xs, ys);\n\n        draw();\n    }\n\n\n   /***************************************************************************\n    *  Drawing text.\n    ***************************************************************************/\n\n    /**\n     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the center <em>x</em>-coordinate of the text\n     * @param  y the center <em>y</em>-coordinate of the text\n     * @param  text the text to write\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    public void text(double x, double y, String text) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(text, \"text\");\n\n        offscreen.setFont(font);\n        FontMetrics metrics = offscreen.getFontMetrics();\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int ws = metrics.stringWidth(text);\n        int hs = metrics.getDescent();\n        offscreen.drawString(text, (float) (xs - ws/2.0), (float) (ys + hs));\n        draw();\n    }\n\n    /**\n     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>) and\n     * rotated by the specified number of degrees.\n     * @param  x the center <em>x</em>-coordinate of the text\n     * @param  y the center <em>y</em>-coordinate of the text\n     * @param  text the text to write\n     * @param  degrees is the number of degrees to rotate counterclockwise\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x}, {@code y}, or {@code degrees} is either NaN or infinite\n     */\n    public void text(double x, double y, String text, double degrees) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(degrees, \"degrees\");\n        validateNotNull(text, \"text\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        offscreen.rotate(Math.toRadians(-degrees), xs, ys);\n        text(x, y, text);\n        offscreen.rotate(Math.toRadians(+degrees), xs, ys);\n    }\n\n    /**\n     * Writes the given text string in the current font, left-aligned at (<em>x</em>, <em>y</em>).\n     * @param  x the <em>x</em>-coordinate of the text\n     * @param  y the <em>y</em>-coordinate of the text\n     * @param  text the text\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    public void textLeft(double x, double y, String text) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(text, \"text\");\n\n        offscreen.setFont(font);\n        FontMetrics metrics = offscreen.getFontMetrics();\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        // int ws = metrics.stringWidth(text);\n        int hs = metrics.getDescent();\n        offscreen.drawString(text, (float) xs, (float) (ys + hs));\n        draw();\n    }\n\n    /**\n     * Writes the given text string in the current font, right-aligned at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the text\n     * @param  y the <em>y</em>-coordinate of the text\n     * @param  text the text to write\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    public void textRight(double x, double y, String text) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(text, \"text\");\n\n        offscreen.setFont(font);\n        FontMetrics metrics = offscreen.getFontMetrics();\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int ws = metrics.stringWidth(text);\n        int hs = metrics.getDescent();\n        offscreen.drawString(text, (float) (xs - ws), (float) (ys + hs));\n        draw();\n    }\n\n    /**\n     * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds\n     * and enables double buffering.\n     * @param t number of milliseconds\n     * @throws IllegalArgumentException if {@code t} is negative\n     * @deprecated replaced by {@link #enableDoubleBuffering()}, {@link #show()}, and {@link #pause(int t)}\n     */\n    @Deprecated\n    public void show(int t) {\n        show();\n        pause(t);\n        enableDoubleBuffering();\n    }\n\n    /**\n     * Pause for t milliseconds. This method is intended to support computer animations.\n     * @param t number of milliseconds\n     * @throws IllegalArgumentException if {@code t} is negative\n     */\n    public void pause(int t) {\n        try {\n            Thread.sleep(t);\n        }\n        catch (InterruptedException e) {\n            System.out.println(\"Error sleeping\");\n        }\n    }\n\n    /**\n     * Copies offscreen buffer to onscreen buffer. There is no reason to call\n     * this method unless double buffering is enabled.\n     */\n    public void show() {\n        onscreen.setBackground(backgroundColor);\n        onscreen.clearRect(0, 0, 2*width, 2*height);\n        onscreen.drawImage(offscreenImage, 0, 0, null);\n\n        // make frame visible upon first call to show()\n        if (frame.isVisible() != isJFrameVisible) {\n            frame.setVisible(isJFrameVisible);\n        }\n\n        frame.repaint();\n    }\n\n    // draw onscreen if defer is false\n    private void draw() {\n        if (!defer) show();\n    }\n\n    /**\n     * Enable double buffering. All subsequent calls to\n     * drawing methods such as {@code line()}, {@code circle()},\n     * and {@code square()} will be deferred until the next call\n     * to show(). Useful for animations.\n     */\n    public void enableDoubleBuffering() {\n        defer = true;\n    }\n\n    /**\n     * Disable double buffering. All subsequent calls to\n     * drawing methods such as {@code line()}, {@code circle()},\n     * and {@code square()} will be displayed on screen when called.\n     * This is the default.\n     */\n    public void disableDoubleBuffering() {\n        defer = false;\n    }\n\n    /**\n     * Saves the drawing to a file in a supported file format\n     * (typically JPEG, PNG, GIF, TIFF, and BMP).\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     *\n     * @param  filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if {@code filename} has invalid filetype extension\n     * @throws IllegalArgumentException if cannot write the file {@code filename}\n     */\n    public void save(String filename) {\n        validateNotNull(filename, \"filename\");\n        if (filename.length() == 0) {\n            throw new IllegalArgumentException(\"argument to save() is the empty string\");\n        }\n\n        File file = new File(filename);\n        String suffix = filename.substring(filename.lastIndexOf('.') + 1);\n        if (!filename.contains(\".\") || suffix.length() == 0) {\n            throw new IllegalArgumentException(\"the filename '\" + filename + \"' has no file extension, such as .jpg or .png\");\n        }\n\n        try {\n            // if the file format supports transparency (such as PNG or GIF)\n            if (ImageIO.write(onscreenImage, suffix, file)) return;\n\n            // if the file format does not support transparency (such as JPEG or BMP)\n            BufferedImage saveImage = new BufferedImage(2*width, 2*height, BufferedImage.TYPE_INT_RGB);\n            saveImage.createGraphics().drawImage(onscreenImage, 0, 0, Color.WHITE, null);\n            if (ImageIO.write(saveImage, suffix, file)) return;\n\n            // failed to save the file; probably wrong format\n            throw new IllegalArgumentException(\"the filetype '\" + suffix + \"' is not supported\");\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not write the file + \" + filename, e);\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void actionPerformed(ActionEvent event) {\n        FileDialog chooser = new FileDialog(frame, \"Use a .png or .jpg extension\", FileDialog.SAVE);\n        chooser.setVisible(true);\n        String selectedDirectory = chooser.getDirectory();\n        String selectedFilename = chooser.getFile();\n        if (selectedDirectory != null && selectedFilename != null) {\n            try {\n                save(selectedDirectory + selectedFilename);\n            }\n            catch (IllegalArgumentException e) {\n                System.err.println(e.getMessage());\n            }\n        }\n    }\n\n\n\n   /***************************************************************************\n    *  Event-based interactions.\n    ***************************************************************************/\n\n    /**\n     * Adds a {@link DrawListener} to listen to keyboard and mouse events.\n     *\n     * @param listener the {\\tt DrawListener} argument\n     */\n    public void addListener(DrawListener listener) {\n        // ensure there is a window for listening to events\n        show();\n        listeners.add(listener);\n    }\n\n\n\n\n   /***************************************************************************\n    *  Mouse interactions.\n    ***************************************************************************/\n\n    /**\n     * Returns true if the mouse is being pressed.\n     *\n     * @return {@code true} if the mouse is being pressed;\n     *         {@code false} otherwise\n     */\n    public boolean isMousePressed() {\n        synchronized (mouseLock) {\n            return isMousePressed;\n        }\n    }\n\n    /**\n     * Returns true if the mouse is being pressed.\n     *\n     * @return {@code true} if the mouse is being pressed;\n     *         {@code false} otherwise\n     * @deprecated replaced by {@link #isMousePressed()}\n     */\n    @Deprecated\n    public boolean mousePressed() {\n        synchronized (mouseLock) {\n            return isMousePressed;\n        }\n    }\n\n    /**\n     * Returns the x-coordinate of the mouse.\n     * @return the x-coordinate of the mouse\n     */\n    public double mouseX() {\n        synchronized (mouseLock) {\n            return mouseX;\n        }\n    }\n\n    /**\n     * Returns the y-coordinate of the mouse.\n     *\n     * @return the y-coordinate of the mouse\n     */\n    public double mouseY() {\n        synchronized (mouseLock) {\n            return mouseY;\n        }\n    }\n\n\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseEntered(MouseEvent event) {\n        // this body is intentionally left empty\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseExited(MouseEvent event) {\n        // this body is intentionally left empty\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mousePressed(MouseEvent event) {\n        synchronized (mouseLock) {\n            mouseX = userX(event.getX());\n            mouseY = userY(event.getY());\n            isMousePressed = true;\n        }\n        if (event.getButton() == MouseEvent.BUTTON1) {\n            for (DrawListener listener : listeners)\n                listener.mousePressed(userX(event.getX()), userY(event.getY()));\n        }\n\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseReleased(MouseEvent event) {\n        synchronized (mouseLock) {\n            isMousePressed = false;\n        }\n        if (event.getButton() == MouseEvent.BUTTON1) {\n            for (DrawListener listener : listeners)\n                listener.mouseReleased(userX(event.getX()), userY(event.getY()));\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseClicked(MouseEvent event) {\n        if (event.getButton() == MouseEvent.BUTTON1) {\n            for (DrawListener listener : listeners)\n                listener.mouseClicked(userX(event.getX()), userY(event.getY()));\n        }\n    }\n\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseDragged(MouseEvent event)  {\n        synchronized (mouseLock) {\n            mouseX = userX(event.getX());\n            mouseY = userY(event.getY());\n        }\n        // doesn't seem to work if a button is specified\n        for (DrawListener listener : listeners)\n            listener.mouseDragged(userX(event.getX()), userY(event.getY()));\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseMoved(MouseEvent event) {\n        synchronized (mouseLock) {\n            mouseX = userX(event.getX());\n            mouseY = userY(event.getY());\n        }\n    }\n\n\n   /***************************************************************************\n    *  Keyboard interactions.\n    ***************************************************************************/\n\n    /**\n     * Returns true if the user has typed a key.\n     *\n     * @return {@code true} if the user has typed a key; {@code false} otherwise\n     */\n    public boolean hasNextKeyTyped() {\n        synchronized (keyLock) {\n            return !keysTyped.isEmpty();\n        }\n    }\n\n    /**\n     * The next key typed by the user.\n     *\n     * @return the next key typed by the user\n     */\n    public char nextKeyTyped() {\n        synchronized (keyLock) {\n            return keysTyped.removeLast();\n        }\n    }\n\n   /**\n     * Returns true if the keycode is being pressed.\n     * <p>\n     * This method takes as an argument the keycode (corresponding to a physical key).\n     * It can handle action keys (such as F1 and arrow keys) and modifier keys\n     * (such as shift and control).\n     * See {@link KeyEvent} for a description of key codes.\n     *\n     * @param  keycode the keycode to check\n     * @return {@code true} if {@code keycode} is currently being pressed;\n     *         {@code false} otherwise\n     */\n    public boolean isKeyPressed(int keycode) {\n        synchronized (keyLock) {\n            return keysDown.contains(keycode);\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void keyTyped(KeyEvent event) {\n        synchronized (keyLock) {\n            keysTyped.addFirst(event.getKeyChar());\n        }\n\n        // notify all listeners\n        for (DrawListener listener : listeners)\n            listener.keyTyped(event.getKeyChar());\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void keyPressed(KeyEvent event) {\n        synchronized (keyLock) {\n            keysDown.add(event.getKeyCode());\n        }\n\n        // notify all listeners\n        for (DrawListener listener : listeners)\n            listener.keyPressed(event.getKeyCode());\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void keyReleased(KeyEvent event) {\n        synchronized (keyLock) {\n            keysDown.remove(event.getKeyCode());\n        }\n\n        // notify all listeners\n        for (DrawListener listener : listeners)\n            listener.keyReleased(event.getKeyCode());\n    }\n\n   /***************************************************************************\n    *  Timer events.\n    ***************************************************************************/\n\n   /**\n     * Sets a timer that calls update() method a specified number of times\n     * per second.\n     * <p>\n     * @param  callsPerSecond calls per second\n     */\n    public void enableTimer(int callsPerSecond) {\n        disableTimer();\n        timer = new Timer();\n        timer.schedule(new MyTimerTask(), 0, (int) Math.round(1000.0 / callsPerSecond));\n    }\n\n    public void disableTimer() {\n        if (timer != null) timer.cancel();\n    }\n\n    private class MyTimerTask extends TimerTask {\n        public void run() {\n            for (DrawListener listener : listeners)\n                listener.update();\n        }\n    }\n\n   /***************************************************************************\n    *  For improved resolution on Mac Retina displays.\n    ***************************************************************************/\n\n    private static class RetinaImageIcon extends ImageIcon {\n\n        public RetinaImageIcon(Image image) {\n            super(image);\n        }\n\n        public int getIconWidth() {\n            return super.getIconWidth() / 2;\n        }\n\n        /**\n         * Returns the height of the icon.\n         *\n         * @return the height in pixels of this icon\n         */\n        public int getIconHeight() {\n            return super.getIconHeight() / 2;\n        }\n\n        public synchronized void paintIcon(Component c, Graphics g, int x, int y) {\n            Graphics2D g2 = (Graphics2D) g.create();\n            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);\n            g2.setRenderingHint(RenderingHints.KEY_RENDERING,     RenderingHints.VALUE_RENDER_QUALITY);\n            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  RenderingHints.VALUE_ANTIALIAS_ON);\n            g2.scale(0.5, 0.5);\n            super.paintIcon(c, g2, x * 2, y * 2);\n            g2.dispose();\n        }\n    }\n\n    /**\n     * Test client.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // create one drawing window\n        Draw draw1 = new Draw();\n        draw1.setTitle(\"Test client 1\");\n        draw1.square(0.2, 0.8, 0.1);\n        draw1.filledSquare(0.8, 0.8, 0.2);\n        draw1.circle(0.8, 0.2, 0.2);\n        draw1.setPenColor(Draw.MAGENTA);\n        draw1.setPenRadius(0.02);\n        draw1.arc(0.8, 0.2, 0.1, 200, 45);\n\n\n        // create another one\n        Draw draw2 = new Draw();\n        draw2.setCanvasSize(900, 200);\n        draw2.setTitle(\"Test client 2\");\n        // draw a blue diamond\n        draw2.setPenRadius();\n        draw2.setPenColor(Draw.BLUE);\n        double[] x = { 0.1, 0.2, 0.3, 0.2 };\n        double[] y = { 0.2, 0.3, 0.2, 0.1 };\n        draw2.filledPolygon(x, y);\n\n        // text\n        draw2.setPenColor(Draw.BLACK);\n        draw2.text(0.2, 0.5, \"black text\");\n        draw2.setPenColor(Draw.WHITE);\n        draw2.text(0.2, 0.2, \"white text\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/DrawListener.java",
    "content": "/******************************************************************************\n *  Compilation:  javac DrawListener.java\n *  Execution:    none\n *  Dependencies: none\n *\n *  Interface that accompanies Draw.java.\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The <code>DrawListener</code> interface provides a basic capability for\n *  responding to keyboard in mouse events from {@link Draw} via callbacks.\n *  You can see some examples in\n *  <a href=\"https://introcs.cs.princeton.edu/java/36inheritance\">Section 3.6</a>.\n *\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic interface DrawListener {\n\n    /**\n     * Invoked when the mouse has been pressed.\n     *\n     * @param x the x-coordinate of the mouse\n     * @param y the y-coordinate of the mouse\n     */\n    default void mousePressed(double x, double y) {\n        // does nothing by default\n    }\n\n    /**\n     * Invoked when the mouse has been dragged.\n     *\n     * @param x the x-coordinate of the mouse\n     * @param y the y-coordinate of the mouse\n     */\n    default void mouseDragged(double x, double y) {\n        // does nothing by default\n    }\n\n    /**\n     * Invoked when the mouse has been released.\n     *\n     * @param x the x-coordinate of the mouse\n     * @param y the y-coordinate of the mouse\n     */\n    default void mouseReleased(double x, double y) {\n        // does nothing by default\n    }\n\n    /**\n     * Invoked when the mouse has been clicked (pressed and released).\n     * A mouse click is triggered only if the user presses a mouse button\n     * and then releases it quickly, without moving the mouse.\n     * It does not work with touch events.\n     * The {@link mousePressed} method is generally preferred for\n     * detecting mouse clicks.\n     *\n     * @param x the x-coordinate of the mouse\n     * @param y the y-coordinate of the mouse\n     */\n    default void mouseClicked(double x, double y) {\n        // does nothing by default\n    }\n\n    /**\n     * Invoked when a key has been typed.\n     *\n     * @param c the character typed\n     */\n    default void keyTyped(char c) {\n        // does nothing by default\n    }\n\n    /**\n     * Invoked when a key has been pressed.\n     *\n     * @param keycode the key combination pressed\n     */\n    default void keyPressed(int keycode) {\n        // does nothing by default\n    }\n\n    /**\n     * Invoked when a key has been released.\n     *\n     * @param keycode the key combination released\n     */\n    default void keyReleased(int keycode) {\n        // does nothing by default\n    }\n\n    /**\n     * Gets called at regular time intervals.\n     */\n    default void update() {\n        // does nothing by default\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Edge.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Edge.java\n *  Execution:    java Edge\n *  Dependencies: StdOut.java\n *\n *  Immutable weighted edge.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Edge} class represents a weighted edge in an\n *  {@link EdgeWeightedGraph}. Each edge consists of two integers\n *  (naming the two vertices) and a real-value weight. The data type\n *  provides methods for accessing the two endpoints of the edge and\n *  the weight. The natural order for this data type is by\n *  ascending order of weight.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/43mst\">Section 4.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Edge implements Comparable<Edge> {\n\n    private final int v;\n    private final int w;\n    private final double weight;\n\n    /**\n     * Initializes an edge between vertices {@code v} and {@code w} of\n     * the given {@code weight}.\n     *\n     * @param  v one vertex\n     * @param  w the other vertex\n     * @param  weight the weight of this edge\n     * @throws IllegalArgumentException if either {@code v} or {@code w}\n     *         is a negative integer\n     * @throws IllegalArgumentException if {@code weight} is {@code NaN}\n     */\n    public Edge(int v, int w, double weight) {\n        if (v < 0) throw new IllegalArgumentException(\"vertex index must be a non-negative integer\");\n        if (w < 0) throw new IllegalArgumentException(\"vertex index must be a non-negative integer\");\n        if (Double.isNaN(weight)) throw new IllegalArgumentException(\"Weight is NaN\");\n        this.v = v;\n        this.w = w;\n        this.weight = weight;\n    }\n\n    /**\n     * Returns the weight of this edge.\n     *\n     * @return the weight of this edge\n     */\n    public double weight() {\n        return weight;\n    }\n\n    /**\n     * Returns either endpoint of this edge.\n     *\n     * @return either endpoint of this edge\n     */\n    public int either() {\n        return v;\n    }\n\n    /**\n     * Returns the endpoint of this edge that is different from the given vertex.\n     *\n     * @param  vertex one endpoint of this edge\n     * @return the other endpoint of this edge\n     * @throws IllegalArgumentException if the vertex is not one of the\n     *         endpoints of this edge\n     */\n    public int other(int vertex) {\n        if      (vertex == v) return w;\n        else if (vertex == w) return v;\n        else throw new IllegalArgumentException(\"Illegal endpoint\");\n    }\n\n    /**\n     * Compares two edges by weight.\n     * Note that {@code compareTo()} is not consistent with {@code equals()},\n     * which uses the reference equality implementation inherited from {@code Object}.\n     *\n     * @param  that the other edge\n     * @return a negative integer, zero, or positive integer depending on whether\n     *         the weight of this is less than, equal to, or greater than the\n     *         argument edge\n     */\n    @Override\n    public int compareTo(Edge that) {\n        return Double.compare(this.weight, that.weight);\n    }\n\n    /**\n     * Returns a string representation of this edge.\n     *\n     * @return a string representation of this edge\n     */\n    public String toString() {\n        return String.format(\"%d-%d %.5f\", v, w, weight);\n    }\n\n    /**\n     * Unit tests the {@code Edge} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Edge e = new Edge(12, 34, 5.67);\n        StdOut.println(e);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/EdgeWeightedDigraph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac EdgeWeightedDigraph.java\n *  Execution:    java EdgeWeightedDigraph digraph.txt\n *  Dependencies: Bag.java DirectedEdge.java\n *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWD.txt\n *                https://algs4.cs.princeton.edu/44sp/mediumEWD.txt\n *                https://algs4.cs.princeton.edu/44sp/largeEWD.txt\n *\n *  An edge-weighted digraph, implemented using adjacency lists.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code EdgeWeightedDigraph} class represents an edge-weighted\n *  digraph of vertices named 0 through <em>V</em> - 1, where each\n *  directed edge is of type {@link DirectedEdge} and has a real-valued weight.\n *  It supports the following two primary operations: add a directed edge\n *  to the digraph and iterate over all edges incident from a given vertex.\n *  It also provides methods for returning the indegree or outdegree of a\n *  vertex, the number of vertices <em>V</em> in the digraph, and\n *  the number of edges <em>E</em> in the digraph.\n *  Parallel edges and self-loops are permitted.\n *  <p>\n *  This implementation uses an <em>adjacency-lists representation</em>, which\n *  is a vertex-indexed array of {@link Bag} objects.\n *  It uses &Theta;(<em>E</em> + <em>V</em>) space, where <em>E</em> is\n *  the number of edges and <em>V</em> is the number of vertices.\n *  All instance methods take &Theta;(1) time. (Though, iterating over\n *  the edges returned by {@link #adj(int)} takes time proportional\n *  to the outdegree of the vertex.)\n *  Constructing an empty edge-weighted digraph with <em>V</em> vertices\n *  takes &Theta;(<em>V</em>) time; constructing an edge-weighted digraph\n *  with <em>E</em> edges and <em>V</em> vertices takes\n *  &Theta;(<em>E</em> + <em>V</em>) time.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class EdgeWeightedDigraph {\n    private static final String NEWLINE = System.getProperty(\"line.separator\");\n\n    private final int V;                // number of vertices in this digraph\n    private int E;                      // number of edges in this digraph\n    private Bag<DirectedEdge>[] adj;    // adj[v] = adjacency list for vertex v\n    private int[] indegree;             // indegree[v] = indegree of vertex v\n\n    /**\n     * Initializes an empty edge-weighted digraph with {@code V} vertices and 0 edges.\n     *\n     * @param  V the number of vertices\n     * @throws IllegalArgumentException if {@code V < 0}\n     */\n    public EdgeWeightedDigraph(int V) {\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices in a Digraph must be non-negative\");\n        this.V = V;\n        this.E = 0;\n        this.indegree = new int[V];\n        adj = (Bag<DirectedEdge>[]) new Bag[V];\n        for (int v = 0; v < V; v++)\n            adj[v] = new Bag<DirectedEdge>();\n    }\n\n    /**\n     * Initializes a random edge-weighted digraph with {@code V} vertices and <em>E</em> edges.\n     *\n     * @param  V the number of vertices\n     * @param  E the number of edges\n     * @throws IllegalArgumentException if {@code V < 0}\n     * @throws IllegalArgumentException if {@code E < 0}\n     */\n    public EdgeWeightedDigraph(int V, int E) {\n        this(V);\n        if (E < 0) throw new IllegalArgumentException(\"Number of edges in a Digraph must be non-negative\");\n        for (int i = 0; i < E; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            double weight = 0.01 * StdRandom.uniformInt(100);\n            DirectedEdge e = new DirectedEdge(v, w, weight);\n            addEdge(e);\n        }\n    }\n\n    /**\n     * Initializes an edge-weighted digraph from the specified input stream.\n     * The format is the number of vertices <em>V</em>,\n     * followed by the number of edges <em>E</em>,\n     * followed by <em>E</em> pairs of vertices and edge weights,\n     * with each entry separated by whitespace.\n     *\n     * @param  in the input stream\n     * @throws IllegalArgumentException if {@code in} is {@code null}\n     * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range\n     * @throws IllegalArgumentException if the number of vertices or edges is negative\n     */\n    public EdgeWeightedDigraph(In in) {\n        if (in == null) throw new IllegalArgumentException(\"argument is null\");\n        try {\n            this.V = in.readInt();\n            if (V < 0) throw new IllegalArgumentException(\"number of vertices in a Digraph must be non-negative\");\n            indegree = new int[V];\n            adj = (Bag<DirectedEdge>[]) new Bag[V];\n            for (int v = 0; v < V; v++) {\n                adj[v] = new Bag<DirectedEdge>();\n            }\n\n            int E = in.readInt();\n            if (E < 0) throw new IllegalArgumentException(\"Number of edges must be non-negative\");\n            for (int i = 0; i < E; i++) {\n                int v = in.readInt();\n                int w = in.readInt();\n                validateVertex(v);\n                validateVertex(w);\n                double weight = in.readDouble();\n                addEdge(new DirectedEdge(v, w, weight));\n            }\n        }\n        catch (NoSuchElementException e) {\n            throw new IllegalArgumentException(\"invalid input format in EdgeWeightedDigraph constructor\", e);\n        }\n    }\n\n    /**\n     * Initializes a new edge-weighted digraph that is a deep copy of {@code G}.\n     *\n     * @param  G the edge-weighted digraph to copy\n     */\n    public EdgeWeightedDigraph(EdgeWeightedDigraph G) {\n        this(G.V());\n        this.E = G.E();\n        for (int v = 0; v < G.V(); v++)\n            this.indegree[v] = G.indegree(v);\n        for (int v = 0; v < G.V(); v++) {\n            // reverse so that adjacency list is in same order as original\n            Stack<DirectedEdge> reverse = new Stack<DirectedEdge>();\n            for (DirectedEdge e : G.adj[v]) {\n                reverse.push(e);\n            }\n            for (DirectedEdge e : reverse) {\n                adj[v].add(e);\n            }\n        }\n    }\n\n    /**\n     * Returns the number of vertices in this edge-weighted digraph.\n     *\n     * @return the number of vertices in this edge-weighted digraph\n     */\n    public int V() {\n        return V;\n    }\n\n    /**\n     * Returns the number of edges in this edge-weighted digraph.\n     *\n     * @return the number of edges in this edge-weighted digraph\n     */\n    public int E() {\n        return E;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Adds the directed edge {@code e} to this edge-weighted digraph.\n     *\n     * @param  e the edge\n     * @throws IllegalArgumentException unless endpoints of edge are between {@code 0}\n     *         and {@code V-1}\n     */\n    public void addEdge(DirectedEdge e) {\n        int v = e.from();\n        int w = e.to();\n        validateVertex(v);\n        validateVertex(w);\n        adj[v].add(e);\n        indegree[w]++;\n        E++;\n    }\n\n\n    /**\n     * Returns the directed edges incident from vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the directed edges incident from vertex {@code v} as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> adj(int v) {\n        validateVertex(v);\n        return adj[v];\n    }\n\n    /**\n     * Returns the number of directed edges incident from vertex {@code v}.\n     * This is known as the <em>outdegree</em> of vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the outdegree of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int outdegree(int v) {\n        validateVertex(v);\n        return adj[v].size();\n    }\n\n    /**\n     * Returns the number of directed edges incident to vertex {@code v}.\n     * This is known as the <em>indegree</em> of vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the indegree of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int indegree(int v) {\n        validateVertex(v);\n        return indegree[v];\n    }\n\n    /**\n     * Returns all directed edges in this edge-weighted digraph.\n     * To iterate over the edges in this edge-weighted digraph, use foreach notation:\n     * {@code for (DirectedEdge e : G.edges())}.\n     *\n     * @return all edges in this edge-weighted digraph, as an iterable\n     */\n    public Iterable<DirectedEdge> edges() {\n        Bag<DirectedEdge> list = new Bag<DirectedEdge>();\n        for (int v = 0; v < V; v++) {\n            for (DirectedEdge e : adj(v)) {\n                list.add(e);\n            }\n        }\n        return list;\n    }\n\n    /**\n     * Returns a string representation of this edge-weighted digraph.\n     *\n     * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,\n     *         followed by the <em>V</em> adjacency lists of edges\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(V + \" \" + E + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            s.append(v + \": \");\n            for (DirectedEdge e : adj[v]) {\n                s.append(e + \"  \");\n            }\n            s.append(NEWLINE);\n        }\n        return s.toString();\n    }\n\n    /**\n     * Returns a string representation of this edge-weighted digraph in DOT format,\n     * suitable for visualization with Graphviz.\n     *\n     * To visualize the graph, install Graphviz (e.g., \"brew install graphviz\").\n     * Then use one of the graph visualization tools\n     *    - dot    (hierarchical or layer drawing)\n     *    - neato  (spring model)\n     *    - fdp    (force-directed placement)\n     *    - sfdp   (scalable force-directed placement)\n     *    - twopi  (radial layout)\n     *\n     * For example, the following commands will create graph drawings in SVG\n     * and PDF formats\n     *    - dot input.dot -Tsvg -o output.svg\n     *    - dot input.dot -Tpdf -o output.pdf\n     *\n     * To change the digraph attributes (e.g., vertex and edge shapes, arrows, colors)\n     *  in the DOT format, see https://graphviz.org/doc/info/lang.html\n     *\n     * @return a string representation of this edge-weighted digraph in DOT format\n     */\n    public String toDot() {\n        StringBuilder s = new StringBuilder();\n        s.append(\"digraph {\" + NEWLINE);\n        s.append(\"node[shape=circle, style=filled, fixedsize=true, width=0.3, fontsize=\\\"10pt\\\"]\" + NEWLINE);\n        s.append(\"edge[arrowhead=normal, fontsize=\\\"9pt\\\"]\" + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            for (DirectedEdge e : adj[v]) {\n                int w = e.to();\n                s.append(v + \" -> \" + w + \" [label=\\\"\" + e.weight() + \"\\\"]\" + NEWLINE);\n            }\n        }\n        s.append(\"}\" + NEWLINE);\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code EdgeWeightedDigraph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);\n        StdOut.println(G);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/EdgeWeightedDirectedCycle.java",
    "content": "/******************************************************************************\n *  Compilation:  javac EdgeWeightedDirectedCycle.java\n *  Execution:    java EdgeWeightedDirectedCycle V E F\n *  Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Stack.java\n *\n *  Finds a directed cycle in an edge-weighted digraph.\n *  Runs in O(E + V) time.\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code EdgeWeightedDirectedCycle} class represents a data type for\n *  determining whether an edge-weighted digraph has a directed cycle.\n *  The <em>hasCycle</em> operation determines whether the edge-weighted\n *  digraph has a directed cycle and, if so, the <em>cycle</em> operation\n *  returns one.\n *  <p>\n *  This implementation uses <em>depth-first search</em>.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted digraph).\n *  <p>\n *  See {@link Topological} to compute a topological order if the\n *  edge-weighted digraph is acyclic.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class EdgeWeightedDirectedCycle {\n    private boolean[] marked;             // marked[v] = has vertex v been marked?\n    private DirectedEdge[] edgeTo;        // edgeTo[v] = previous edge on path to v\n    private boolean[] onStack;            // onStack[v] = is vertex on the stack?\n    private Stack<DirectedEdge> cycle;    // directed cycle (or null if no such cycle)\n\n    /**\n     * Determines whether the edge-weighted digraph {@code G} has a directed cycle and,\n     * if so, finds such a cycle.\n     * @param G the edge-weighted digraph\n     */\n    public EdgeWeightedDirectedCycle(EdgeWeightedDigraph G) {\n        marked  = new boolean[G.V()];\n        onStack = new boolean[G.V()];\n        edgeTo  = new DirectedEdge[G.V()];\n        for (int v = 0; v < G.V(); v++)\n            if (!marked[v]) dfs(G, v);\n\n        // check that digraph has a cycle\n        assert check();\n    }\n\n    // check that algorithm computes either the topological order or finds a directed cycle\n    private void dfs(EdgeWeightedDigraph G, int v) {\n        onStack[v] = true;\n        marked[v] = true;\n        for (DirectedEdge e : G.adj(v)) {\n            int w = e.to();\n\n            // short circuit if directed cycle found\n            if (cycle != null) return;\n\n            // found new vertex, so recur\n            else if (!marked[w]) {\n                edgeTo[w] = e;\n                dfs(G, w);\n            }\n\n            // trace back directed cycle\n            else if (onStack[w]) {\n                cycle = new Stack<DirectedEdge>();\n\n                DirectedEdge f = e;\n                while (f.from() != w) {\n                    cycle.push(f);\n                    f = edgeTo[f.from()];\n                }\n                cycle.push(f);\n\n                return;\n            }\n        }\n\n        onStack[v] = false;\n    }\n\n    /**\n     * Does the edge-weighted digraph have a directed cycle?\n     * @return {@code true} if the edge-weighted digraph has a directed cycle,\n     * {@code false} otherwise\n     */\n    public boolean hasCycle() {\n        return cycle != null;\n    }\n\n    /**\n     * Returns a directed cycle if the edge-weighted digraph has a directed cycle,\n     * and {@code null} otherwise.\n     * @return a directed cycle (as an iterable) if the edge-weighted digraph\n     *    has a directed cycle, and {@code null} otherwise\n     */\n    public Iterable<DirectedEdge> cycle() {\n        return cycle;\n    }\n\n\n    // certify that digraph is either acyclic or has a directed cycle\n    private boolean check() {\n\n        // edge-weighted digraph is cyclic\n        if (hasCycle()) {\n            // verify cycle\n            DirectedEdge first = null, last = null;\n            for (DirectedEdge e : cycle()) {\n                if (first == null) first = e;\n                if (last != null) {\n                    if (last.to() != e.from()) {\n                        System.err.printf(\"cycle edges %s and %s not incident\\n\", last, e);\n                        return false;\n                    }\n                }\n                last = e;\n            }\n\n            // cycle() contains no edges\n            if (first == null || last == null) {\n                System.err.printf(\"cycle contains no edges\\n\");\n                return false;\n            }\n\n            // first and last edges in cycle are not incident\n            if (last.to() != first.from()) {\n                System.err.printf(\"cycle edges %s and %s not incident\\n\", last, first);\n                return false;\n            }\n        }\n\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code EdgeWeightedDirectedCycle} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // create random DAG with V vertices and E edges; then add F random edges\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        int F = Integer.parseInt(args[2]);\n        EdgeWeightedDigraph G = new EdgeWeightedDigraph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < E; i++) {\n            int v, w;\n            do {\n                v = StdRandom.uniformInt(V);\n                w = StdRandom.uniformInt(V);\n            } while (v >= w);\n            double weight = StdRandom.uniformDouble(0.0, 1.0);\n            G.addEdge(new DirectedEdge(v, w, weight));\n        }\n\n        // add F extra edges\n        for (int i = 0; i < F; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            double weight = StdRandom.uniformDouble(0.0, 1.0);\n            G.addEdge(new DirectedEdge(v, w, weight));\n        }\n\n        StdOut.println(G);\n\n        // find a directed cycle\n        EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G);\n        if (finder.hasCycle()) {\n            StdOut.print(\"Cycle: \");\n            for (DirectedEdge e : finder.cycle()) {\n                StdOut.print(e + \" \");\n            }\n            StdOut.println();\n        }\n\n        // or give topological sort\n        else {\n            StdOut.println(\"No directed cycle\");\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/EdgeWeightedGraph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac EdgeWeightedGraph.java\n *  Execution:    java EdgeWeightedGraph filename.txt\n *  Dependencies: Bag.java Edge.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt\n *\n *  An edge-weighted undirected graph, implemented using adjacency lists.\n *  Parallel edges and self-loops are permitted.\n *\n *  % java EdgeWeightedGraph tinyEWG.txt\n *  8 16\n *  0: 6-0 0.58000  0-2 0.26000  0-4 0.38000  0-7 0.16000\n *  1: 1-3 0.29000  1-2 0.36000  1-7 0.19000  1-5 0.32000\n *  2: 6-2 0.40000  2-7 0.34000  1-2 0.36000  0-2 0.26000  2-3 0.17000\n *  3: 3-6 0.52000  1-3 0.29000  2-3 0.17000\n *  4: 6-4 0.93000  0-4 0.38000  4-7 0.37000  4-5 0.35000\n *  5: 1-5 0.32000  5-7 0.28000  4-5 0.35000\n *  6: 6-4 0.93000  6-0 0.58000  3-6 0.52000  6-2 0.40000\n *  7: 2-7 0.34000  1-7 0.19000  0-7 0.16000  5-7 0.28000  4-7 0.37000\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code EdgeWeightedGraph} class represents an edge-weighted\n *  graph of vertices named 0 through <em>V</em> – 1, where each\n *  undirected edge is of type {@link Edge} and has a real-valued weight.\n *  It supports the following two primary operations: add an edge to the graph,\n *  iterate over all of the edges incident with a vertex. It also provides\n *  methods for returning the degree of a vertex, the number of vertices\n *  <em>V</em> in the graph, and the number of edges <em>E</em> in the graph.\n *  Parallel edges and self-loops are permitted.\n *  By convention, a self-loop <em>v</em>-<em>v</em> appears in the\n *  adjacency list of <em>v</em> twice and contributes two to the degree\n *  of <em>v</em>.\n *  <p>\n *  This implementation uses an <em>adjacency-lists representation</em>, which\n *  is a vertex-indexed array of {@link Bag} objects.\n *  It uses &Theta;(<em>E</em> + <em>V</em>) space, where <em>E</em> is\n *  the number of edges and <em>V</em> is the number of vertices.\n *  All instance methods take &Theta;(1) time. (Though, iterating over\n *  the edges returned by {@link #adj(int)} takes time proportional\n *  to the degree of the vertex.)\n *  Constructing an empty edge-weighted graph with <em>V</em> vertices takes\n *  &Theta;(<em>V</em>) time; constructing an edge-weighted graph with\n *  <em>E</em> edges and <em>V</em> vertices takes\n *  &Theta;(<em>E</em> + <em>V</em>) time.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/43mst\">Section 4.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class EdgeWeightedGraph {\n    private static final String NEWLINE = System.getProperty(\"line.separator\");\n\n    private final int V;\n    private int E;\n    private Bag<Edge>[] adj;\n\n    /**\n     * Initializes an empty edge-weighted graph with {@code V} vertices and 0 edges.\n     *\n     * @param  V the number of vertices\n     * @throws IllegalArgumentException if {@code V < 0}\n     */\n    public EdgeWeightedGraph(int V) {\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices must be non-negative\");\n        this.V = V;\n        this.E = 0;\n        adj = (Bag<Edge>[]) new Bag[V];\n        for (int v = 0; v < V; v++) {\n            adj[v] = new Bag<Edge>();\n        }\n    }\n\n    /**\n     * Initializes a random edge-weighted graph with {@code V} vertices and <em>E</em> edges.\n     *\n     * @param  V the number of vertices\n     * @param  E the number of edges\n     * @throws IllegalArgumentException if {@code V < 0}\n     * @throws IllegalArgumentException if {@code E < 0}\n     */\n    public EdgeWeightedGraph(int V, int E) {\n        this(V);\n        if (E < 0) throw new IllegalArgumentException(\"Number of edges must be non-negative\");\n        for (int i = 0; i < E; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            double weight = 0.01 * StdRandom.uniformInt(0, 100);\n            Edge e = new Edge(v, w, weight);\n            addEdge(e);\n        }\n    }\n\n    /**\n     * Initializes an edge-weighted graph from an input stream.\n     * The format is the number of vertices <em>V</em>,\n     * followed by the number of edges <em>E</em>,\n     * followed by <em>E</em> pairs of vertices and edge weights,\n     * with each entry separated by whitespace.\n     *\n     * @param  in the input stream\n     * @throws IllegalArgumentException if {@code in} is {@code null}\n     * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range\n     * @throws IllegalArgumentException if the number of vertices or edges is negative\n     */\n    public EdgeWeightedGraph(In in) {\n        if (in == null) throw new IllegalArgumentException(\"argument is null\");\n\n        try {\n            V = in.readInt();\n            adj = (Bag<Edge>[]) new Bag[V];\n            for (int v = 0; v < V; v++) {\n                adj[v] = new Bag<Edge>();\n            }\n\n            int E = in.readInt();\n            if (E < 0) throw new IllegalArgumentException(\"Number of edges must be non-negative\");\n            for (int i = 0; i < E; i++) {\n                int v = in.readInt();\n                int w = in.readInt();\n                validateVertex(v);\n                validateVertex(w);\n                double weight = in.readDouble();\n                Edge e = new Edge(v, w, weight);\n                addEdge(e);\n            }\n        }\n        catch (NoSuchElementException e) {\n            throw new IllegalArgumentException(\"invalid input format in EdgeWeightedGraph constructor\", e);\n        }\n\n    }\n\n    /**\n     * Initializes a new edge-weighted graph that is a deep copy of {@code G}.\n     *\n     * @param  G the edge-weighted graph to copy\n     */\n    public EdgeWeightedGraph(EdgeWeightedGraph G) {\n        this(G.V());\n        this.E = G.E();\n        for (int v = 0; v < G.V(); v++) {\n            // reverse so that adjacency list is in same order as original\n            Stack<Edge> reverse = new Stack<Edge>();\n            for (Edge e : G.adj[v]) {\n                reverse.push(e);\n            }\n            for (Edge e : reverse) {\n                adj[v].add(e);\n            }\n        }\n    }\n\n\n    /**\n     * Returns the number of vertices in this edge-weighted graph.\n     *\n     * @return the number of vertices in this edge-weighted graph\n     */\n    public int V() {\n        return V;\n    }\n\n    /**\n     * Returns the number of edges in this edge-weighted graph.\n     *\n     * @return the number of edges in this edge-weighted graph\n     */\n    public int E() {\n        return E;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Adds the undirected edge {@code e} to this edge-weighted graph.\n     *\n     * @param  e the edge\n     * @throws IllegalArgumentException unless both endpoints are between {@code 0} and {@code V-1}\n     */\n    public void addEdge(Edge e) {\n        int v = e.either();\n        int w = e.other(v);\n        validateVertex(v);\n        validateVertex(w);\n        adj[v].add(e);\n        adj[w].add(e);\n        E++;\n    }\n\n    /**\n     * Returns the edges incident with vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the edges incident with vertex {@code v} as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Edge> adj(int v) {\n        validateVertex(v);\n        return adj[v];\n    }\n\n    /**\n     * Returns the degree of vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the degree of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int degree(int v) {\n        validateVertex(v);\n        return adj[v].size();\n    }\n\n    /**\n     * Returns all edges in this edge-weighted graph.\n     * To iterate over the edges in this edge-weighted graph, use foreach notation:\n     * {@code for (Edge e : G.edges())}.\n     *\n     * @return all edges in this edge-weighted graph, as an iterable\n     */\n    public Iterable<Edge> edges() {\n        Bag<Edge> list = new Bag<Edge>();\n        for (int v = 0; v < V; v++) {\n            int selfLoops = 0;\n            for (Edge e : adj(v)) {\n                if (e.other(v) > v) {\n                    list.add(e);\n                }\n                // add only one copy of each self loop (self loops will be consecutive)\n                else if (e.other(v) == v) {\n                    if (selfLoops % 2 == 0) list.add(e);\n                    selfLoops++;\n                }\n            }\n        }\n        return list;\n    }\n\n    /**\n     * Returns a string representation of the edge-weighted graph.\n     * This method takes time proportional to <em>E</em> + <em>V</em>.\n     *\n     * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,\n     *         followed by the <em>V</em> adjacency lists of edges\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(V + \" \" + E + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            s.append(v + \": \");\n            for (Edge e : adj[v]) {\n                s.append(e + \"  \");\n            }\n            s.append(NEWLINE);\n        }\n        return s.toString();\n    }\n\n    /**\n     * Returns a string representation of this edge-weighted graph in DOT format,\n     * suitable for visualization with Graphviz.\n     *\n     * To visualize the graph, install Graphviz (e.g., \"brew install graphviz\").\n     * Then use one of the graph visualization tools\n     *    - dot    (hierarchical or layer drawing)\n     *    - neato  (spring model)\n     *    - fdp    (force-directed placement)\n     *    - sfdp   (scalable force-directed placement)\n     *    - twopi  (radial layout)\n     *\n     * For example, the following commands will create graph drawings in SVG\n     * and PDF formats\n     *    - dot input.dot -Tsvg -o output.svg\n     *    - dot input.dot -Tpdf -o output.pdf\n     *\n     * To change the graph attributes (e.g., vertex and edge shapes, arrows, colors)\n     *  in the DOT format, see https://graphviz.org/doc/info/lang.html\n     *\n     * @return a string representation of this edge-weighted graph in DOT format\n     */\n    public String toDot() {\n        StringBuilder s = new StringBuilder();\n        s.append(\"graph {\" + NEWLINE);\n        s.append(\"node[shape=circle, style=filled, fixedsize=true, width=0.3, fontsize=\\\"10pt\\\"]\" + NEWLINE);\n        s.append(\"edge[arrowhead=normal, fontsize=\\\"9pt\\\"]\" + NEWLINE);\n        for (Edge e : edges()) {\n            int v = e.either();\n            int w = e.other(v);\n            s.append(v + \" --\" + w + \" [label=\\\"\" + e.weight() + \"\\\"]\" + NEWLINE);\n        }\n        s.append(\"}\" + NEWLINE);\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code EdgeWeightedGraph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph graph = new EdgeWeightedGraph(in);\n        StdOut.println(graph);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/EulerianCycle.java",
    "content": "/******************************************************************************\n *  Compilation:  javac EulerianCycle.java\n *  Execution:    java  EulerianCycle V E\n *  Dependencies: Graph.java Stack.java StdOut.java\n *\n *  Find an Eulerian cycle in a graph, if one exists.\n *\n *  Runs in O(E + V) time.\n *\n *  This implementation is trickier than the one for digraphs because\n *  when we use edge v-w from v's adjacency list, we must be careful\n *  not to use the second copy of the edge from w's adjacency list.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code EulerianCycle} class represents a data type\n *  for finding an Eulerian cycle or path in a graph.\n *  An <em>Eulerian cycle</em> is a cycle (not necessarily simple) that\n *  uses every edge in the graph exactly once.\n *  <p>\n *  This implementation uses a nonrecursive depth-first search.\n *  The constructor takes &Theta;(<em>E</em> + <em>V</em>) time in the worst\n *  case, where <em>E</em> is the number of edges and <em>V</em> is the\n *  number of vertices\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>E</em> + <em>V</em>) extra space in the worst case\n *  (not including the graph).\n *  <p>\n *  To compute Eulerian paths in graphs, see {@link EulerianPath}.\n *  To compute Eulerian cycles and paths in digraphs, see\n *  {@link DirectedEulerianCycle} and {@link DirectedEulerianPath}.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *  @author Nate Liu\n */\npublic class EulerianCycle {\n    private Stack<Integer> cycle = new Stack<Integer>();  // Eulerian cycle; null if no such cycle\n\n    // an undirected edge, with a field to indicate whether the edge has already been used\n    private static class Edge {\n        private final int v;\n        private final int w;\n        private boolean isUsed;\n\n        public Edge(int v, int w) {\n            this.v = v;\n            this.w = w;\n            isUsed = false;\n        }\n\n        // returns the other vertex of the edge\n        public int other(int vertex) {\n            if      (vertex == v) return w;\n            else if (vertex == w) return v;\n            else throw new IllegalArgumentException(\"Illegal endpoint\");\n        }\n    }\n\n    /**\n     * Computes an Eulerian cycle in the specified graph, if one exists.\n     *\n     * @param graph the graph\n     */\n    public EulerianCycle(Graph graph) {\n\n        // must have at least one edge\n        if (graph.E() == 0) return;\n\n        // necessary condition: all vertices have even degree\n        // (this test is needed, or it might find an Eulerian path instead of cycle)\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) % 2 != 0)\n                return;\n\n        // create local view of adjacency lists, to iterate one vertex at a time\n        // the helper Edge data type is used to avoid exploring both copies of an edge v-w\n        Queue<Edge>[] adj = (Queue<Edge>[]) new Queue[graph.V()];\n        for (int v = 0; v < graph.V(); v++)\n            adj[v] = new Queue<Edge>();\n\n        for (int v = 0; v < graph.V(); v++) {\n            int selfLoops = 0;\n            for (int w : graph.adj(v)) {\n                // careful with self loops\n                if (v == w) {\n                    if (selfLoops % 2 == 0) {\n                        Edge e = new Edge(v, w);\n                        adj[v].enqueue(e);\n                        adj[w].enqueue(e);\n                    }\n                    selfLoops++;\n                }\n                else if (v < w) {\n                    Edge e = new Edge(v, w);\n                    adj[v].enqueue(e);\n                    adj[w].enqueue(e);\n                }\n            }\n        }\n\n        // initialize stack with any non-isolated vertex\n        int s = nonIsolatedVertex(graph);\n        Stack<Integer> stack = new Stack<Integer>();\n        stack.push(s);\n\n        // greedily search through edges in iterative DFS style\n        cycle = new Stack<Integer>();\n        while (!stack.isEmpty()) {\n            int v = stack.pop();\n            while (!adj[v].isEmpty()) {\n                Edge edge = adj[v].dequeue();\n                if (edge.isUsed) continue;\n                edge.isUsed = true;\n                stack.push(v);\n                v = edge.other(v);\n            }\n            // push vertex with no more leaving edges to cycle\n            cycle.push(v);\n        }\n\n        // check if all edges are used\n        if (cycle.size() != graph.E() + 1)\n            cycle = null;\n\n        assert certifySolution(graph);\n    }\n\n    /**\n     * Returns the sequence of vertices on an Eulerian cycle.\n     *\n     * @return the sequence of vertices on an Eulerian cycle;\n     *         {@code null} if no such cycle\n     */\n    public Iterable<Integer> cycle() {\n        return cycle;\n    }\n\n    /**\n     * Returns true if the graph has an Eulerian cycle.\n     *\n     * @return {@code true} if the graph has an Eulerian cycle;\n     *         {@code false} otherwise\n     */\n    public boolean hasEulerianCycle() {\n        return cycle != null;\n    }\n\n    // returns any non-isolated vertex; -1 if no such vertex\n    private static int nonIsolatedVertex(Graph graph) {\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) > 0)\n                return v;\n        return -1;\n    }\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // Determines whether a graph has an Eulerian cycle using necessary\n    // and sufficient conditions (without computing the cycle itself):\n    //    - at least one edge\n    //    - degree(v) is even for every vertex v\n    //    - the graph is connected (ignoring isolated vertices)\n    private static boolean satisfiesNecessaryAndSufficientConditions(Graph graph) {\n\n        // Condition 0: at least 1 edge\n        if (graph.E() == 0) return false;\n\n        // Condition 1: degree(v) is even for every vertex\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) % 2 != 0)\n                return false;\n\n        // Condition 2: graph is connected, ignoring isolated vertices\n        int s = nonIsolatedVertex(graph);\n        BreadthFirstPaths bfs = new BreadthFirstPaths(graph, s);\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) > 0 && !bfs.hasPathTo(v))\n                return false;\n\n        return true;\n    }\n\n    // check that solution is correct\n    private boolean certifySolution(Graph graph) {\n\n        // internal consistency check\n        if (hasEulerianCycle() == (cycle() == null)) return false;\n\n        // hashEulerianCycle() returns correct value\n        if (hasEulerianCycle() != satisfiesNecessaryAndSufficientConditions(graph)) return false;\n\n        // nothing else to check if no Eulerian cycle\n        if (cycle == null) return true;\n\n        // check that cycle() uses correct number of edges\n        if (cycle.size() != graph.E() + 1) return false;\n\n        // check that cycle() is a cycle of G\n        // TODO\n\n        // check that first and last vertices in cycle() are the same\n        int first = -1, last = -1;\n        for (int v : cycle()) {\n            if (first == -1) first = v;\n            last = v;\n        }\n        if (first != last) return false;\n\n        return true;\n    }\n\n    private static void unitTest(Graph graph, String description) {\n        StdOut.println(description);\n        StdOut.println(\"-------------------------------------\");\n        StdOut.print(graph);\n\n        EulerianCycle euler = new EulerianCycle(graph);\n\n        StdOut.print(\"Eulerian cycle: \");\n        if (euler.hasEulerianCycle()) {\n            for (int v : euler.cycle()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n        else {\n            StdOut.println(\"none\");\n        }\n        StdOut.println();\n    }\n\n\n    /**\n     * Unit tests the {@code EulerianCycle} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n\n        // Eulerian cycle\n        Graph graph1 = GraphGenerator.eulerianCycle(V, E);\n        unitTest(graph1, \"Eulerian cycle\");\n\n        // Eulerian path\n        Graph graph2 = GraphGenerator.eulerianPath(V, E);\n        unitTest(graph2, \"Eulerian path\");\n\n        // empty graph\n        Graph graph3 = new Graph(V);\n        unitTest(graph3, \"empty graph\");\n\n        // self loop\n        Graph graph4 = new Graph(V);\n        int v4 = StdRandom.uniformInt(V);\n        graph4.addEdge(v4, v4);\n        unitTest(graph4, \"single self loop\");\n\n        // union of two disjoint cycles\n        Graph H1 = GraphGenerator.eulerianCycle(V/2, E/2);\n        Graph H2 = GraphGenerator.eulerianCycle(V - V/2, E - E/2);\n        int[] perm = new int[V];\n        for (int i = 0; i < V; i++)\n            perm[i] = i;\n        StdRandom.shuffle(perm);\n        Graph graph5 = new Graph(V);\n        for (int v = 0; v < H1.V(); v++)\n            for (int w : H1.adj(v))\n                graph5.addEdge(perm[v], perm[w]);\n        for (int v = 0; v < H2.V(); v++)\n            for (int w : H2.adj(v))\n                graph5.addEdge(perm[V/2 + v], perm[V/2 + w]);\n        unitTest(graph5, \"Union of two disjoint cycles\");\n\n        // random digraph\n        Graph graph6 = GraphGenerator.simple(V, E);\n        unitTest(graph6, \"simple graph\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/EulerianPath.java",
    "content": "/******************************************************************************\n *  Compilation:  javac EulerianPath.java\n *  Execution:    java EulerianPath V E\n *  Dependencies: Graph.java Stack.java StdOut.java\n *\n *  Find an Eulerian path in a graph, if one exists.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code EulerianPath} class represents a data type\n *  for finding an Eulerian path in a graph.\n *  An <em>Eulerian path</em> is a path (not necessarily simple) that\n *  uses every edge in the graph exactly once.\n *  <p>\n *  This implementation uses a nonrecursive depth-first search.\n *  The constructor takes &Theta;(<em>E</em> + <em>V</em>) time in the worst\n *  case, where <em>E</em> is the number of edges and <em>V</em> is\n *  the number of vertices.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>E</em> + <em>V</em>) extra space in the worst case\n *  (not including the digraph).\n *  <p>\n *  To compute Eulerian cycles in graphs, see {@link EulerianCycle}.\n *  To compute Eulerian cycles and paths in digraphs, see\n *  {@link DirectedEulerianCycle} and {@link DirectedEulerianPath}.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n * @author Robert Sedgewick\n * @author Kevin Wayne\n * @author Nate Liu\n */\npublic class EulerianPath {\n    private Stack<Integer> path = null;   // Eulerian path; null if no suh path\n\n    // an undirected edge, with a field to indicate whether the edge has already been used\n    private static class Edge {\n        private final int v;\n        private final int w;\n        private boolean isUsed;\n\n        public Edge(int v, int w) {\n            this.v = v;\n            this.w = w;\n            isUsed = false;\n        }\n\n        // returns the other vertex of the edge\n        public int other(int vertex) {\n            if      (vertex == v) return w;\n            else if (vertex == w) return v;\n            else throw new IllegalArgumentException(\"Illegal endpoint\");\n        }\n    }\n\n    /**\n     * Computes an Eulerian path in the specified graph, if one exists.\n     *\n     * @param graph the graph\n     */\n    public EulerianPath(Graph graph) {\n\n        // find vertex from which to start potential Eulerian path:\n        // a vertex v with odd degree(v) if it exits;\n        // otherwise a vertex with degree(v) > 0\n        int oddDegreeVertices = 0;\n        int s = nonIsolatedVertex(graph);\n        for (int v = 0; v < graph.V(); v++) {\n            if (graph.degree(v) % 2 != 0) {\n                oddDegreeVertices++;\n                s = v;\n            }\n        }\n\n        // graph can't have an Eulerian path\n        // (this condition is needed for correctness)\n        if (oddDegreeVertices > 2) return;\n\n        // special case for graph with zero edges (has a degenerate Eulerian path)\n        if (s == -1) s = 0;\n\n        // create local view of adjacency lists, to iterate one vertex at a time\n        // the helper Edge data type is used to avoid exploring both copies of an edge v-w\n        Queue<Edge>[] adj = (Queue<Edge>[]) new Queue[graph.V()];\n        for (int v = 0; v < graph.V(); v++)\n            adj[v] = new Queue<Edge>();\n\n        for (int v = 0; v < graph.V(); v++) {\n            int selfLoops = 0;\n            for (int w : graph.adj(v)) {\n                // careful with self loops\n                if (v == w) {\n                    if (selfLoops % 2 == 0) {\n                        Edge e = new Edge(v, w);\n                        adj[v].enqueue(e);\n                        adj[w].enqueue(e);\n                    }\n                    selfLoops++;\n                }\n                else if (v < w) {\n                    Edge e = new Edge(v, w);\n                    adj[v].enqueue(e);\n                    adj[w].enqueue(e);\n                }\n            }\n        }\n\n        // initialize stack with any non-isolated vertex\n        Stack<Integer> stack = new Stack<Integer>();\n        stack.push(s);\n\n        // greedily search through edges in iterative DFS style\n        path = new Stack<Integer>();\n        while (!stack.isEmpty()) {\n            int v = stack.pop();\n            while (!adj[v].isEmpty()) {\n                Edge edge = adj[v].dequeue();\n                if (edge.isUsed) continue;\n                edge.isUsed = true;\n                stack.push(v);\n                v = edge.other(v);\n            }\n            // push vertex with no more leaving edges to path\n            path.push(v);\n        }\n\n        // check if all edges are used\n        if (path.size() != graph.E() + 1)\n            path = null;\n\n        assert certifySolution(graph);\n    }\n\n    /**\n     * Returns the sequence of vertices on an Eulerian path.\n     *\n     * @return the sequence of vertices on an Eulerian path;\n     *         {@code null} if no such path\n     */\n    public Iterable<Integer> path() {\n        return path;\n    }\n\n    /**\n     * Returns true if the graph has an Eulerian path.\n     *\n     * @return {@code true} if the graph has an Eulerian path;\n     *         {@code false} otherwise\n     */\n    public boolean hasEulerianPath() {\n        return path != null;\n    }\n\n\n    // returns any non-isolated vertex; -1 if no such vertex\n    private static int nonIsolatedVertex(Graph graph) {\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) > 0)\n                return v;\n        return -1;\n    }\n\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // Determines whether a graph has an Eulerian path using necessary\n    // and sufficient conditions (without computing the path itself):\n    //    - degree(v) is even for every vertex, except for possibly two\n    //    - the graph is connected (ignoring isolated vertices)\n    // This method is solely for unit testing.\n    private static boolean satisfiesNecessaryAndSufficientConditions(Graph graph) {\n        if (graph.E() == 0) return true;\n\n        // Condition 1: degree(v) is even except for possibly two\n        int oddDegreeVertices = 0;\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) % 2 != 0)\n                oddDegreeVertices++;\n        if (oddDegreeVertices > 2) return false;\n\n        // Condition 2: graph is connected, ignoring isolated vertices\n        int s = nonIsolatedVertex(graph);\n        BreadthFirstPaths bfs = new BreadthFirstPaths(graph, s);\n        for (int v = 0; v < graph.V(); v++)\n            if (graph.degree(v) > 0 && !bfs.hasPathTo(v))\n                return false;\n\n        return true;\n    }\n\n    // check that solution is correct\n    private boolean certifySolution(Graph graph) {\n\n        // internal consistency check\n        if (hasEulerianPath() == (path() == null)) return false;\n\n        // hashEulerianPath() returns correct value\n        if (hasEulerianPath() != satisfiesNecessaryAndSufficientConditions(graph)) return false;\n\n        // nothing else to check if no Eulerian path\n        if (path == null) return true;\n\n        // check that path() uses correct number of edges\n        if (path.size() != graph.E() + 1) return false;\n\n        // check that path() is a path in G\n        // TODO\n\n        return true;\n    }\n\n\n    private static void unitTest(Graph graph, String description) {\n        StdOut.println(description);\n        StdOut.println(\"-------------------------------------\");\n        StdOut.print(graph);\n\n        EulerianPath euler = new EulerianPath(graph);\n\n        StdOut.print(\"Eulerian path:  \");\n        if (euler.hasEulerianPath()) {\n            for (int v : euler.path()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n        else {\n            StdOut.println(\"none\");\n        }\n        StdOut.println();\n    }\n\n\n    /**\n     * Unit tests the {@code EulerianPath} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n\n\n        // Eulerian cycle\n        Graph graph1 = GraphGenerator.eulerianCycle(V, E);\n        unitTest(graph1, \"Eulerian cycle\");\n\n        // Eulerian path\n        Graph graph2 = GraphGenerator.eulerianPath(V, E);\n        unitTest(graph2, \"Eulerian path\");\n\n        // add one random edge\n        Graph graph3 = new Graph(graph2);\n        graph3.addEdge(StdRandom.uniformInt(V), StdRandom.uniformInt(V));\n        unitTest(graph3, \"one random edge added to Eulerian path\");\n\n        // self loop\n        Graph graph4 = new Graph(V);\n        int v4 = StdRandom.uniformInt(V);\n        graph4.addEdge(v4, v4);\n        unitTest(graph4, \"single self loop\");\n\n        // single edge\n        Graph graph5 = new Graph(V);\n        graph5.addEdge(StdRandom.uniformInt(V), StdRandom.uniformInt(V));\n        unitTest(graph5, \"single edge\");\n\n        // empty graph\n        Graph graph6 = new Graph(V);\n        unitTest(graph6, \"empty graph\");\n\n        // random graph\n        Graph graph7 = GraphGenerator.simple(V, E);\n        unitTest(graph7, \"simple graph\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FFT.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FFT.java\n *  Execution:    java FFT n\n *  Dependencies: Complex.java\n *\n *  Compute the FFT and inverse FFT of a length n complex sequence.\n *  Bare-bones implementation that runs in O(n log n) time. Our goal\n *  is to optimize the clarity of the code, rather than performance.\n *\n *  Limitations\n *  -----------\n *   -  assumes n is a power of 2\n *\n *   -  not the most memory efficient algorithm (because it uses\n *      an object type for representing complex numbers and because\n *      it re-allocates memory for the subarray, instead of doing\n *      in-place or reusing a single temporary array)\n *\n *\n *  % java FFT 4\n *  x\n *  -------------------\n *  -0.03480425839330703\n *  0.07910192950176387\n *  0.7233322451735928\n *  0.1659819820667019\n *\n *  y = fft(x)\n *  -------------------\n *  0.9336118983487516\n *  -0.7581365035668999 + 0.08688005256493803i\n *  0.44344407521182005\n *  -0.7581365035668999 - 0.08688005256493803i\n *\n *  z = ifft(y)\n *  -------------------\n *  -0.03480425839330703\n *  0.07910192950176387 + 2.6599344570851287E-18i\n *  0.7233322451735928\n *  0.1659819820667019 - 2.6599344570851287E-18i\n *\n *  c = cconvolve(x, x)\n *  -------------------\n *  0.5506798633981853\n *  0.23461407150576394 - 4.033186818023279E-18i\n *  -0.016542951108772352\n *  0.10288019294318276 + 4.033186818023279E-18i\n *\n *  d = convolve(x, x)\n *  -------------------\n *  0.001211336402308083 - 3.122502256758253E-17i\n *  -0.005506167987577068 - 5.058885073636224E-17i\n *  -0.044092969479563274 + 2.1934338938072244E-18i\n *  0.10288019294318276 - 3.6147323062478115E-17i\n *  0.5494685269958772 + 3.122502256758253E-17i\n *  0.240120239493341 + 4.655566391833896E-17i\n *  0.02755001837079092 - 2.1934338938072244E-18i\n *  4.01805098805014E-17i\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code FFT} class provides methods for computing the\n *  FFT (Fast-Fourier Transform), inverse FFT, linear convolution,\n *  and circular convolution of a complex array.\n *  <p>\n *  It is a bare-bones implementation that runs in <em>n</em> log <em>n</em> time,\n *  where <em>n</em> is the length of the complex array. For simplicity,\n *  <em>n</em> must be a power of 2.\n *  Our goal is to optimize the clarity of the code, rather than performance.\n *  It is not the most memory efficient implementation because it uses\n *  objects to represent complex numbers and it re-allocates memory\n *  for the subarray, instead of doing in-place or reusing a single\n *  temporary array.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  In practice, there will be floating-point rounding error.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/99scientific\">Section 9.9</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FFT {\n\n    private static final Complex ZERO = new Complex(0, 0);\n\n    // Do not instantiate.\n    private FFT() { }\n\n    /**\n     * Returns the FFT of the specified complex array.\n     *\n     * @param  x the complex array\n     * @return the FFT of the complex array {@code x}\n     * @throws IllegalArgumentException if the length of {@code x} is not a power of 2\n     */\n    public static Complex[] fft(Complex[] x) {\n        int n = x.length;\n\n        // base case\n        if (n == 1) {\n            return new Complex[] { x[0] };\n        }\n\n        // radix 2 Cooley-Tukey FFT\n        if (n % 2 != 0) {\n            throw new IllegalArgumentException(\"n is not a power of 2\");\n        }\n\n        // fft of even terms\n        Complex[] even = new Complex[n/2];\n        for (int k = 0; k < n/2; k++) {\n            even[k] = x[2*k];\n        }\n        Complex[] q = fft(even);\n\n        // fft of odd terms\n        Complex[] odd = even;  // reuse the array\n        for (int k = 0; k < n/2; k++) {\n            odd[k] = x[2*k + 1];\n        }\n        Complex[] r = fft(odd);\n\n        // combine\n        Complex[] y = new Complex[n];\n        for (int k = 0; k < n/2; k++) {\n            double kth = -2 * k * Math.PI / n;\n            Complex wk = new Complex(Math.cos(kth), Math.sin(kth));\n            y[k]       = q[k].plus(wk.times(r[k]));\n            y[k + n/2] = q[k].minus(wk.times(r[k]));\n        }\n        return y;\n    }\n\n\n    /**\n     * Returns the inverse FFT of the specified complex array.\n     *\n     * @param  x the complex array\n     * @return the inverse FFT of the complex array {@code x}\n     * @throws IllegalArgumentException if the length of {@code x} is not a power of 2\n     */\n    public static Complex[] ifft(Complex[] x) {\n        int n = x.length;\n        Complex[] y = new Complex[n];\n\n        // take conjugate\n        for (int i = 0; i < n; i++) {\n            y[i] = x[i].conjugate();\n        }\n\n        // compute forward FFT\n        y = fft(y);\n\n        // take conjugate again\n        for (int i = 0; i < n; i++) {\n            y[i] = y[i].conjugate();\n        }\n\n        // divide by n\n        for (int i = 0; i < n; i++) {\n            y[i] = y[i].scale(1.0 / n);\n        }\n\n        return y;\n\n    }\n\n    /**\n     * Returns the circular convolution of the two specified complex arrays.\n     *\n     * @param  x one complex array\n     * @param  y the other complex array\n     * @return the circular convolution of {@code x} and {@code y}\n     * @throws IllegalArgumentException if the length of {@code x} does not equal\n     *         the length of {@code y} or if the length is not a power of 2\n     */\n    public static Complex[] cconvolve(Complex[] x, Complex[] y) {\n\n        // should probably pad x and y with 0s so that they have same length\n        // and are powers of 2\n        if (x.length != y.length) {\n            throw new IllegalArgumentException(\"Dimensions don't agree\");\n        }\n\n        int n = x.length;\n\n        // compute FFT of each sequence\n        Complex[] a = fft(x);\n        Complex[] b = fft(y);\n\n        // point-wise multiply\n        Complex[] c = new Complex[n];\n        for (int i = 0; i < n; i++) {\n            c[i] = a[i].times(b[i]);\n        }\n\n        // compute inverse FFT\n        return ifft(c);\n    }\n\n    /**\n     * Returns the linear convolution of the two specified complex arrays.\n     *\n     * @param  x one complex array\n     * @param  y the other complex array\n     * @return the linear convolution of {@code x} and {@code y}\n     * @throws IllegalArgumentException if the length of {@code x} does not equal\n     *         the length of {@code y} or if the length is not a power of 2\n     */\n    public static Complex[] convolve(Complex[] x, Complex[] y) {\n        Complex[] a = new Complex[2*x.length];\n        for (int i = 0; i < x.length; i++)\n            a[i] = x[i];\n        for (int i = x.length; i < 2*x.length; i++)\n            a[i] = ZERO;\n\n        Complex[] b = new Complex[2*y.length];\n        for (int i = 0; i < y.length; i++)\n            b[i] = y[i];\n        for (int i = y.length; i < 2*y.length; i++)\n            b[i] = ZERO;\n\n        return cconvolve(a, b);\n    }\n\n    // display an array of Complex numbers to standard output\n    private static void show(Complex[] x, String title) {\n        StdOut.println(title);\n        StdOut.println(\"-------------------\");\n        for (int i = 0; i < x.length; i++) {\n            StdOut.println(x[i]);\n        }\n        StdOut.println();\n    }\n\n\n   /***************************************************************************\n    *  Test client.\n    ***************************************************************************/\n\n    /**\n     * Unit tests the {@code FFT} class.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = Integer.parseInt(args[0]);\n        Complex[] x = new Complex[n];\n\n        // original data\n        for (int i = 0; i < n; i++) {\n            x[i] = new Complex(i, 0);\n            x[i] = new Complex(StdRandom.uniformDouble(-1.0, 1.0), 0);\n        }\n        show(x, \"x\");\n\n        // FFT of original data\n        Complex[] y = fft(x);\n        show(y, \"y = fft(x)\");\n\n        // take inverse FFT\n        Complex[] z = ifft(y);\n        show(z, \"z = ifft(y)\");\n\n        // circular convolution of x with itself\n        Complex[] c = cconvolve(x, x);\n        show(c, \"c = cconvolve(x, x)\");\n\n        // linear convolution of x with itself\n        Complex[] d = convolve(x, x);\n        show(d, \"d = convolve(x, x)\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FarthestPair.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FarthestPair.java\n *  Execution:    java FarthestPair < input.txt\n *  Dependencies: GrahamScan.java Point2D.java\n *  Data files:   https://algs4.cs.princeton.edu/99hull/rs1423.txt\n *                https://algs4.cs.princeton.edu/99hull/kw1260.txt\n *\n *  Given a set of n points in the plane, find the farthest pair\n *  (equivalently, compute the diameter of the set of points).\n *\n *  Computes the convex hull of the set of points and using the\n *  rotating calipers method to find all antipodal point pairs\n *  and the farthest pair.\n *\n *  % java FarthestPair < input100.txt\n *  42697.98170874122 from (32011.0, 3140.0) to (822.0, 32301.0)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code FarthestPair} data type computes the farthest pair of points\n *  in a set of <em>n</em> points in the plane and provides accessor methods\n *  for getting the farthest pair of points and the distance between them.\n *  The distance between two points is their Euclidean distance.\n *  <p>\n *  This implementation computes the convex hull of the set of points and\n *  uses the rotating calipers method to find all antipodal point pairs\n *  and the farthest pair.\n *  It runs in O(<em>n</em> log <em>n</em>) time in the worst case and uses\n *  O(<em>N</em>) extra space.\n *  See also {@link ClosestPair} and {@link GrahamScan}.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/99hull\">Section 9.9</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FarthestPair {\n\n    // farthest pair of points and distance\n    private Point2D best1, best2;\n    private double bestDistanceSquared = Double.NEGATIVE_INFINITY;\n\n    /**\n     * Computes the farthest pair of points in the specified array of points.\n     *\n     * @param  points the array of points\n     * @throws IllegalArgumentException if {@code points} is {@code null} or if any\n     *         entry in {@code points[]} is {@code null}\n     */\n    public FarthestPair(Point2D[] points) {\n        if (points == null) throw new IllegalArgumentException(\"constructor argument is null\");\n        for (int i = 0; i < points.length; i++) {\n            if (points[i] == null) throw new IllegalArgumentException(\"array element \" + i + \" is null\");\n        }\n\n        GrahamScan graham = new GrahamScan(points);\n\n        // single point\n        if (points.length <= 1) return;\n\n        // number of points on the hull\n        int m = 0;\n        for (Point2D p : graham.hull())\n            m++;\n\n        // the hull, in counterclockwise order hull[1] to hull[m]\n        Point2D[] hull = new Point2D[m+1];\n        m = 1;\n        for (Point2D p : graham.hull()) {\n            hull[m++] = p;\n        }\n        m--;\n\n        // all points are equal\n        if (m == 1) return;\n\n        // points are collinear\n        if (m == 2) {\n            best1 = hull[1];\n            best2 = hull[2];\n            bestDistanceSquared = best1.distanceSquaredTo(best2);\n            return;\n        }\n\n        // k = farthest vertex from edge from hull[1] to hull[m]\n        int k = 2;\n        while (Point2D.area2(hull[m], hull[1], hull[k+1]) > Point2D.area2(hull[m], hull[1], hull[k])) {\n            k++;\n        }\n\n        int j = k;\n        for (int i = 1; i <= k && j <= m; i++) {\n            // StdOut.println(\"hull[i] + \" and \" + hull[j] + \" are antipodal\");\n            if (hull[i].distanceSquaredTo(hull[j]) > bestDistanceSquared) {\n                best1 = hull[i];\n                best2 = hull[j];\n                bestDistanceSquared = hull[i].distanceSquaredTo(hull[j]);\n            }\n            while ((j < m) && Point2D.area2(hull[i], hull[i+1], hull[j+1]) > Point2D.area2(hull[i], hull[i+1], hull[j])) {\n                j++;\n                // StdOut.println(hull[i] + \" and \" + hull[j] + \" are antipodal\");\n                double distanceSquared = hull[i].distanceSquaredTo(hull[j]);\n                if (distanceSquared > bestDistanceSquared) {\n                    best1 = hull[i];\n                    best2 = hull[j];\n                    bestDistanceSquared = hull[i].distanceSquaredTo(hull[j]);\n                }\n            }\n        }\n    }\n\n    /**\n     * Returns one of the points in the farthest pair of points.\n     *\n     * @return one of the two points in the farthest pair of points;\n     *         {@code null} if no such point (because there are fewer than 2 points)\n     */\n    public Point2D either() {\n        return best1;\n    }\n\n    /**\n     * Returns the other point in the farthest pair of points.\n     *\n     * @return the other point in the farthest pair of points\n     *         {@code null} if no such point (because there are fewer than 2 points)\n     */\n    public Point2D other() {\n        return best2;\n    }\n\n    /**\n     * Returns the Euclidean distance between the farthest pair of points.\n     * This quantity is also known as the <em>diameter</em> of the set of points.\n     *\n     * @return the Euclidean distance between the farthest pair of points\n     *         {@code Double.POSITIVE_INFINITY} if no such pair of points\n     *         exist (because there are fewer than 2 points)\n     */\n    public double distance() {\n        return Math.sqrt(bestDistanceSquared);\n    }\n\n   /**\n     * Unit tests the {@code FarthestPair} data type.\n     * Reads in an integer {@code n} and {@code n} points (specified by\n     * their <em>x</em>- and <em>y</em>-coordinates) from standard input;\n     * computes a farthest pair of points; and prints the pair to standard\n     * output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        Point2D[] points = new Point2D[n];\n        for (int i = 0; i < n; i++) {\n            int x = StdIn.readInt();\n            int y = StdIn.readInt();\n            points[i] = new Point2D(x, y);\n        }\n        FarthestPair farthest = new FarthestPair(points);\n        StdOut.println(farthest.distance() + \" from \" + farthest.either() + \" to \" + farthest.other());\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FenwickTree.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FenwickTree.java\n *  Execution:    java FenwickTree\n *\n *  A Fenwick tree.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\n\n/**\n * Created by ricardodpsx@gmail.com on 4/01/15.\n * <p>\n * In {@code Fenwick Tree} structure We arrange the array in an smart way to perform efficient <em>range queries and updates</em>.\n * The key point is this: In a fenwick array, each position \"responsible\" for storing cumulative data of N previous positions (N could be 1)\n * For example:\n * array[40] stores: array[40] + array[39] ... + array[32] (8 positions)\n * array[32] stores: array[32] + array[31] ... + array[1]  (32 positions)\n * <p>\n * <strong>But, how do you know how much positions a given index is \"responsible\" for?</strong>\n * <p>\n * To know the number of items that a given array position 'ind' is responsible for\n * We should extract from 'ind' the portion up to the first significant one of the binary representation of 'ind'\n * for example, given ind == 40 (101000 in binary), according to Fenwick algorithm\n * what We want is to extract 1000(8 in decimal).\n * <p>\n * This means that array[40] has cumulative information of 8 array items.\n * But We still need to know the cumulative data bellow array[40 - 8 = 32]\n * 32 is  100000 in binnary, and the portion up to the least significant one is 32 itself!\n * So array[32] has information of 32 items, and We are done!\n * <p>\n * So cummulative data of array[1...40] = array[40] + array[32]\n * Because 40 has information of items from 40 to 32, and 32 has information of items from 32 to  1\n * <p>\n * Memory usage:  O(n)\n *\n * @author Ricardo Pacheco \n */\npublic class FenwickTree {\n\n    int[] array; // 1-indexed array, In this array We save cumulative information to perform efficient range queries and updates\n\n    public FenwickTree(int size) {\n        array = new int[size + 1];\n    }\n\n    /**\n     * Range Sum query from 1 to ind\n     * ind is 1-indexed\n     * <p>\n     * Time-Complexity:    O(log(n))\n     *\n     * @param  ind index\n     * @return sum\n     */\n    public int rsq(int ind) {\n        assert ind > 0;\n        int sum = 0;\n        while (ind > 0) {\n            sum += array[ind];\n            //Extracting the portion up to the first significant one of the binary representation of 'ind' and decrementing ind by that number\n            ind -= ind & (-ind);\n        }\n\n        return sum;\n    }\n\n    /**\n     * Range Sum Query from a to b.\n     * Search for the sum from array index from a to b\n     * a and b are 1-indexed\n     * <p>\n     * Time-Complexity:    O(log(n))\n     *\n     * @param  a left index\n     * @param  b right index\n     * @return sum\n     */\n    public int rsq(int a, int b) {\n        assert b >= a && a > 0 && b > 0;\n\n        return rsq(b) - rsq(a - 1);\n    }\n\n    /**\n     * Update the array at ind and all the affected regions above ind.\n     * ind is 1-indexed\n     * <p>\n     * Time-Complexity:    O(log(n))\n     *\n     * @param  ind   index\n     * @param  value value\n     */\n    public void update(int ind, int value) {\n        assert ind > 0;\n        while (ind < array.length) {\n            array[ind] += value;\n            //Extracting the portion up to the first significant one of the binary representation of 'ind' and incrementing ind by that number\n            ind += ind & (-ind);\n        }\n    }\n\n    public int size() {\n        return array.length - 1;\n    }\n\n\n    /**\n     * Read the following commands:\n     * init n     Initializes the array of size n all zeroes\n     * set a b c    Initializes the array  with [a, b, c ...]\n     * rsq a b      Range Sum Query for the range [a,b]\n     * up  i v      Update the i position of the array with value v.\n     * exit\n     * <p>\n     * The array is 1-indexed\n     * Example:\n     * set 1 2 3 4 5 6\n     * rsq 1 3\n     * Sum from 1 to 3 = 6\n     * rmq 1 3\n     * Min from 1 to 3 = 1\n     * input up 1 3\n     * [3,2,3,4,5,6]\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n\n        FenwickTree ft = null;\n\n        String cmd = \"cmp\";\n        while (true) {\n            String[] line = StdIn.readLine().split(\" \");\n\n            if (line[0].equals(\"exit\")) break;\n\n            int arg1 = 0, arg2 = 0;\n\n            if (line.length > 1) {\n                arg1 = Integer.parseInt(line[1]);\n            }\n            if (line.length > 2) {\n                arg2 = Integer.parseInt(line[2]);\n            }\n\n            if ((!line[0].equals(\"set\") && !line[0].equals(\"init\")) && ft == null) {\n                StdOut.println(\"FenwickTree not initialized\");\n                continue;\n            }\n\n            if (line[0].equals(\"init\")) {\n                ft = new FenwickTree(arg1);\n                for (int i = 1; i <= ft.size(); i++) {\n                    StdOut.print(ft.rsq(i, i) + \" \");\n                }\n                StdOut.println();\n            }\n            else if (line[0].equals(\"set\")) {\n                ft = new FenwickTree(line.length - 1);\n                for (int i = 1; i <= line.length - 1; i++) {\n                    ft.update(i, Integer.parseInt(line[i]));\n                }\n            }\n\n            else if (line[0].equals(\"up\")) {\n                ft.update(arg1, arg2);\n                for (int i = 1; i <= ft.size(); i++) {\n                    StdOut.print(ft.rsq(i, i) + \" \");\n                }\n                StdOut.println();\n            }\n            else if (line[0].equals(\"rsq\")) {\n                StdOut.printf(\"Sum from %d to %d = %d%n\", arg1, arg2, ft.rsq(arg1, arg2));\n            }\n            else {\n                StdOut.println(\"Invalid command\");\n            }\n\n        }\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FibonacciMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation: javac FibonacciMinPQ.java\n *  Execution:\n *\n *  A Fibonacci heap.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.HashMap;\nimport java.util.NoSuchElementException;\nimport java.util.Comparator;\n\n/*\n *  The FibonacciMinPQ class represents a priority queue of generic keys.\n *  It supports the usual insert and delete-the-minimum operations, \n *  along with the merging of two heaps together.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  It is possible to build the priority queue using a Comparator.\n *  If not, the natural order relation between the keys will be used.\n *  \n *  This implementation uses a Fibonacci heap.\n *  The delete-the-minimum operation takes amortized logarithmic time.\n *  The insert, min-key, is-empty, size, union and constructor take constant time.\n *\n *   WARNING: THIS VERSION HAS AT LEAST ONE BUG.\n *\n *  @author Tristan Claverie\n */\npublic class FibonacciMinPQ<Key> implements Iterable<Key> {\n\tprivate Node head;\t\t\t\t\t//Head of the circular root list\n\tprivate Node min;\t\t\t\t\t//Minimum Node of the root list\n\tprivate int size;\t\t\t\t\t//Number of keys in the heap\n\tprivate final Comparator<Key> comp;\t//Comparator over the keys\n\tprivate HashMap<Integer, Node> table = new HashMap<Integer, Node>(); //Used for the consolidate operation\n\t\n\t//Represents a Node of a tree\n\tprivate class Node {\n\t\tKey key;\t\t\t\t\t\t//Key of this Node\n\t\tint order;\t\t\t\t\t\t//Order of the tree rooted by this Node\n\t\tNode prev, next;\t\t\t\t//Siblings of this Node\n\t\tNode child;\t\t\t\t\t\t//Child of this Node\n\t}\n\t\n\t/**\n\t * Initializes an empty priority queue\n\t * Worst case is O(1)\n\t * @param C a Comparator over the Keys\n\t */\n\tpublic FibonacciMinPQ(Comparator<Key> C) {\n\t\tcomp = C;\n\t}\n\t\n    /**\n     * Initializes an empty priority queue\n     * Worst case is O(1)\n     */\n\tpublic FibonacciMinPQ() {\n\t\tcomp = new MyComparator();\n\t}\n\t\n\t/**\n\t * Initializes a priority queue with given keys\n\t * Worst case is O(n)\n\t * @param a an array of keys\n\t */\n\tpublic FibonacciMinPQ(Key[] a) {\n\t\tcomp = new MyComparator();\n\t\tfor (Key k : a) insert(k);\n\t}\n\t\n\t/**\n\t * Initializes a priority queue with given keys\n\t * Worst case is O(n)\n\t * @param C a comparator over the keys\n\t * @param a an array of keys\n\t */\n\tpublic FibonacciMinPQ(Comparator<Key> C, Key[] a) {\n\t\tcomp = C;\n\t\tfor (Key k : a) insert(k);\n\t}\n\n\t/**\n\t * Whether the priority queue is empty\n\t * Worst case is O(1)\n\t * @return true if the priority queue is empty, false if not\n\t */\n\tpublic boolean isEmpty() {\n\t\treturn size == 0;\n\t}\n\n\t/**\n\t * Number of elements currently on the priority queue\n\t * Worst case is O(1)\n\t * @return the number of elements on the priority queue\n\t */\n\tpublic int size() {\n\t\treturn size;\n\t}\n\n\t/**\n\t * Insert a key in the queue\n\t * Worst case is O(1)\n\t * @param key a Key\n\t */\n\tpublic void insert(Key key) {\n\t\tNode x = new Node();\n\t\tx.key = key;\n\t\tsize++;\n\t\thead = insert(x, head);\n\t\tif (min == null) min = head;\n\t\telse \t\t\t min = (greater(min.key, key)) ? head : min;\n\t}\n\n\t/**\n\t * Gets the minimum key currently in the queue\n\t * Worst case is O(1)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key currently in the priority queue\n\t */\n\tpublic Key minKey() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\treturn min.key;\n\t}\n\n\t/**\n\t * Deletes the minimum key\n\t * Worst case is O(log(n)) (amortized)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key\n\t */\n\tpublic Key delMin() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\thead = cut(min, head);\n\t\tNode x = min.child;\n\t\tKey key = min.key;\n\t\tmin.key = null;\n\t\tif (x != null) {\n\t\t\thead = meld(head, x);\n\t\t\tmin.child = null;\n\t\t}\n\t\tsize--;\n\t\tif (!isEmpty()) consolidate();\n\t\telse \t\t\tmin = null;\n\t\treturn key;\n\t}\n\t\n\t/**\n\t * Merges two heaps together\n\t * This operation is destructive\n\t * Worst case is O(1)\n\t * @param that a Fibonacci heap\n\t * @return the union of the two heaps\n\t */\n\tpublic FibonacciMinPQ<Key> union(FibonacciMinPQ<Key> that) {\n\t\tthis.head = meld(head, that.head);\n\t\tthis.min = (greater(this.min.key, that.min.key)) ? that.min : this.min;\n\t\tthis.size = this.size+that.size;\n\t\treturn this;\n\t}\n\t\n\t/*************************************\n\t * General helper functions\n\t ************************************/\n\t\n\t//Compares two keys\n\tprivate boolean greater(Key n, Key m) {\n\t\tif (n == null) return false;\n\t\tif (m == null) return true;\n\t\treturn comp.compare(n,m) > 0;\n\t}\n\t\n\t//Assuming root1 holds a greater key than root2, root2 becomes the new root\n\tprivate void link(Node root1, Node root2) {\n\t\troot2.child = insert(root1, root2.child);\n\t\troot2.order++;\n\t}\n\t\n\t/*************************************\n\t * Function for consolidating all trees in the root list\n\t ************************************/\n\t\n\t//Coalesce the roots, thus reshapes the tree\n\tprivate void consolidate() {\n\t\ttable.clear();\n\t\tNode x = head;\n\t\tint maxOrder = 0;\n\t\tmin = head;\n\t\tNode y = null; Node z = null;\n\t\tdo {\n\t\t\ty = x;\n\t\t\tx = x.next;\n\t\t\tz = table.get(y.order);\n\t\t\twhile (z != null) {\n\t\t\t\ttable.remove(y.order);\n\t\t\t\tif (greater(y.key, z.key)) {\n\t\t\t\t\tlink(y, z);\n\t\t\t\t\ty = z;\n\t\t\t\t} else {\n\t\t\t\t\tlink(z, y);\n\t\t\t\t}\n\t\t\t\tz = table.get(y.order);\n\t\t\t}\n\t\t\ttable.put(y.order, y);\n\t\t\tif (y.order > maxOrder) maxOrder = y.order;\n\t\t} while (x != head);\n\t\thead = null;\n\t\tfor (Node n : table.values()) {\n\t\t\tif (n != null) {\n\t\t\t\tmin = greater(min.key, n.key) ? n : min;\n\t\t\t\thead = insert(n, head);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/*************************************\n\t * General helper functions for manipulating circular lists\n\t ************************************/\n\t\n\t//Inserts a Node in a circular list containing head, returns a new head\n\tprivate Node insert(Node x, Node head) {\n\t\tif (head == null) {\n\t\t\tx.prev = x;\n\t\t\tx.next = x;\n\t\t} else {\n\t\t\thead.prev.next = x;\n\t\t\tx.next = head;\n\t\t\tx.prev = head.prev;\n\t\t\thead.prev = x;\n\t\t}\n\t\treturn x;\n\t}\n\t\n\t//Removes a tree from the list defined by the head pointer\n\tprivate Node cut(Node x, Node head) {\n\t\tif (x.next == x) {\n\t\t\tx.next = null;\n\t\t\tx.prev = null;\n\t\t\treturn null;\n\t\t} else {\n\t\t\tx.next.prev = x.prev;\n\t\t\tx.prev.next = x.next;\n\t\t\tNode res = x.next;\n\t\t\tx.next = null;\n\t\t\tx.prev = null;\n\t\t\tif (head == x)  return res;\n\t\t\telse \t\t\treturn head;\n\t\t}\n\t}\n\t\n\t//Merges two root lists together\n\tprivate Node meld(Node x, Node y) {\n\t\tif (x == null) return y;\n\t\tif (y == null) return x;\n\t\tx.prev.next = y.next;\n\t\ty.next.prev = x.prev;\n\t\tx.prev = y;\n\t\ty.next = x;\n\t\treturn x;\n\t}\n\t\n\t/*************************************\n\t * Iterator\n\t ************************************/\n\t\n\t/**\n\t * Gets an Iterator over the Keys in the priority queue in ascending order\n\t * The Iterator does not implement the remove() method\n\t * iterator() : Worst case is O(n)\n\t * next() : \tWorst case is O(log(n)) (amortized)\n\t * hasNext() : \tWorst case is O(1)\n\t * @return an Iterator over the Keys in the priority queue in ascending order\n\t */\n\t\n\tpublic Iterator<Key> iterator() {\n\t\treturn new MyIterator();\n\t}\n\t\n\tprivate class MyIterator implements Iterator<Key> {\n\t\tprivate FibonacciMinPQ<Key> copy;\n\t\t\n\t\t\n\t\t//Constructor takes linear time\n\t\tpublic MyIterator() {\n\t\t\tcopy = new FibonacciMinPQ<Key>(comp);\n\t\t\tinsertAll(head);\n\t\t}\n\t\t\n\t\tprivate void insertAll(Node head) {\n\t\t\tif (head == null) return;\n\t\t\tNode x = head;\n\t\t\tdo {\n\t\t\t\tcopy.insert(x.key);\n\t\t\t\tinsertAll(x.child);\n\t\t\t\tx = x.next;\n\t\t\t} while (x != head);\n\t\t}\n\t\t\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\t\n\t\tpublic boolean hasNext() {\n\t\t\treturn !copy.isEmpty();\n\t\t}\n\t\t\n\t\t//Takes amortized logarithmic time\n\t\tpublic Key next() {\n\t\t\tif (!hasNext()) throw new NoSuchElementException();\n\t\t\treturn copy.delMin();\n\t\t}\n\t}\n\t\n\t/*************************************\n\t * Comparator\n\t ************************************/\n\t\n\t//default Comparator\n\tprivate class MyComparator implements Comparator<Key> {\n\t\t@Override\n\t\tpublic int compare(Key key1, Key key2) {\n\t\t\treturn ((Comparable<Key>) key1).compareTo(key2);\n\t\t}\n\t}\n\t\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FileIndex.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FileIndex.java\n *  Execution:    java FileIndex file1.txt file2.txt file3.txt ...\n *  Dependencies: ST.java SET.java In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/ex1.txt\n *                https://algs4.cs.princeton.edu/35applications/ex2.txt\n *                https://algs4.cs.princeton.edu/35applications/ex3.txt\n *                https://algs4.cs.princeton.edu/35applications/ex4.txt\n *\n *  % java FileIndex ex*.txt\n *  age\n *   ex3.txt\n *   ex4.txt\n * best\n *   ex1.txt\n * was\n *   ex1.txt\n *   ex2.txt\n *   ex3.txt\n *   ex4.txt\n *\n *  % java FileIndex *.txt\n *\n *  % java FileIndex *.java\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.File;\n\n/**\n *  The {@code FileIndex} class provides a client for indexing a set of files,\n *  specified as command-line arguments. It takes queries from standard input\n *  and prints each file that contains the given query.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FileIndex {\n\n    // Do not instantiate.\n    private FileIndex() { }\n\n    public static void main(String[] args) {\n\n        // key = word, value = set of files containing that word\n        ST<String, SET<File>> st = new ST<String, SET<File>>();\n\n        // create inverted index of all files\n        StdOut.println(\"Indexing files\");\n        for (String filename : args) {\n            StdOut.println(\"  \" + filename);\n            File file = new File(filename);\n            In in = new In(file);\n            while (!in.isEmpty()) {\n                String word = in.readString();\n                if (!st.contains(word)) st.put(word, new SET<File>());\n                SET<File> set = st.get(word);\n                set.add(file);\n            }\n        }\n\n\n        // read queries from standard input, one per line\n        while (!StdIn.isEmpty()) {\n            String query = StdIn.readString();\n            if (st.contains(query)) {\n                SET<File> set = st.get(query);\n                for (File file : set) {\n                    StdOut.println(\"  \" + file.getName());\n                }\n            }\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FlowEdge.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FlowEdge.java\n *  Execution:    java FlowEdge\n *  Dependencies: StdOut.java\n *\n *  Capacitated edge with a flow in a flow network.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code FlowEdge} class represents a capacitated edge with a\n  * flow in a {@link FlowNetwork}. Each edge consists of two integers\n *  (naming the two vertices), a real-valued capacity, and a real-valued\n *  flow. The data type provides methods for accessing the two endpoints\n *  of the directed edge and the weight. It also provides methods for\n *  changing the amount of flow on the edge and determining the residual\n *  capacity of the edge.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/64maxflow\">Section 6.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FlowEdge {\n    // to deal with floating-point roundoff errors\n    private static final double FLOATING_POINT_EPSILON = 1.0E-10;\n\n    private final int v;             // from\n    private final int w;             // to\n    private final double capacity;   // capacity\n    private double flow;             // flow\n\n    /**\n     * Initializes an edge from vertex {@code v} to vertex {@code w} with\n     * the given {@code capacity} and zero flow.\n     * @param v the tail vertex\n     * @param w the head vertex\n     * @param capacity the capacity of the edge\n     * @throws IllegalArgumentException if either {@code v} or {@code w}\n     *    is a negative integer\n     * @throws IllegalArgumentException if {@code capacity < 0.0}\n     */\n    public FlowEdge(int v, int w, double capacity) {\n        if (v < 0) throw new IllegalArgumentException(\"vertex index must be a non-negative integer\");\n        if (w < 0) throw new IllegalArgumentException(\"vertex index must be a non-negative integer\");\n        if (!(capacity >= 0.0)) throw new IllegalArgumentException(\"Edge capacity must be non-negative\");\n        this.v         = v;\n        this.w         = w;\n        this.capacity  = capacity;\n        this.flow      = 0.0;\n    }\n\n    /**\n     * Initializes an edge from vertex {@code v} to vertex {@code w} with\n     * the given {@code capacity} and {@code flow}.\n     * @param v the tail vertex\n     * @param w the head vertex\n     * @param capacity the capacity of the edge\n     * @param flow the flow on the edge\n     * @throws IllegalArgumentException if either {@code v} or {@code w}\n     *    is a negative integer\n     * @throws IllegalArgumentException if {@code capacity} is negative\n     * @throws IllegalArgumentException unless {@code flow} is between\n     *    {@code 0.0} and {@code capacity}.\n     */\n    public FlowEdge(int v, int w, double capacity, double flow) {\n        if (v < 0) throw new IllegalArgumentException(\"vertex index must be a non-negative integer\");\n        if (w < 0) throw new IllegalArgumentException(\"vertex index must be a non-negative integer\");\n        if (!(capacity >= 0.0))  throw new IllegalArgumentException(\"edge capacity must be non-negative\");\n        if (!(flow <= capacity)) throw new IllegalArgumentException(\"flow exceeds capacity\");\n        if (!(flow >= 0.0))      throw new IllegalArgumentException(\"flow must be non-negative\");\n        this.v         = v;\n        this.w         = w;\n        this.capacity  = capacity;\n        this.flow      = flow;\n    }\n\n    /**\n     * Initializes a flow edge from another flow edge.\n     * @param e the edge to copy\n     */\n    public FlowEdge(FlowEdge e) {\n        this.v         = e.v;\n        this.w         = e.w;\n        this.capacity  = e.capacity;\n        this.flow      = e.flow;\n    }\n\n    /**\n     * Returns the tail vertex of the edge.\n     * @return the tail vertex of the edge\n     */\n    public int from() {\n        return v;\n    }\n\n    /**\n     * Returns the head vertex of the edge.\n     * @return the head vertex of the edge\n     */\n    public int to() {\n        return w;\n    }\n\n    /**\n     * Returns the capacity of the edge.\n     * @return the capacity of the edge\n     */\n    public double capacity() {\n        return capacity;\n    }\n\n    /**\n     * Returns the flow on the edge.\n     * @return the flow on the edge\n     */\n    public double flow() {\n        return flow;\n    }\n\n    /**\n     * Returns the endpoint of the edge that is different from the given vertex\n     * (unless the edge represents a self-loop in which case it returns the same vertex).\n     * @param vertex one endpoint of the edge\n     * @return the endpoint of the edge that is different from the given vertex\n     *   (unless the edge represents a self-loop in which case it returns the same vertex)\n     * @throws IllegalArgumentException if {@code vertex} is not one of the endpoints\n     *   of the edge\n     */\n    public int other(int vertex) {\n        if      (vertex == v) return w;\n        else if (vertex == w) return v;\n        else throw new IllegalArgumentException(\"invalid endpoint\");\n    }\n\n    /**\n     * Returns the residual capacity of the edge in the direction\n     *  to the given {@code vertex}.\n     * @param vertex one endpoint of the edge\n     * @return the residual capacity of the edge in the direction to the given vertex\n     *   If {@code vertex} is the tail vertex, the residual capacity equals\n     *   {@code capacity() - flow()}; if {@code vertex} is the head vertex, the\n     *   residual capacity equals {@code flow()}.\n     * @throws IllegalArgumentException if {@code vertex} is not one of the endpoints of the edge\n     */\n    public double residualCapacityTo(int vertex) {\n        if      (vertex == v) return flow;              // backward edge\n        else if (vertex == w) return capacity - flow;   // forward edge\n        else throw new IllegalArgumentException(\"invalid endpoint\");\n    }\n\n    /**\n     * Increases the flow on the edge in the direction to the given vertex.\n     * If {@code vertex} is the tail vertex, this increases the flow on the edge by {@code delta};\n     * if {@code vertex} is the head vertex, this decreases the flow on the edge by {@code delta}.\n     * @param vertex one endpoint of the edge\n     * @param delta amount by which to increase flow\n     * @throws IllegalArgumentException if {@code vertex} is not one of the endpoints\n     *         of the edge\n     * @throws IllegalArgumentException if {@code delta} makes the flow\n     *         on the edge either negative or larger than its capacity\n     * @throws IllegalArgumentException if {@code delta} is {@code NaN}\n     */\n    public void addResidualFlowTo(int vertex, double delta) {\n        if (!(delta >= 0.0)) throw new IllegalArgumentException(\"Delta must be non-negative\");\n\n        if      (vertex == v) flow -= delta;           // backward edge\n        else if (vertex == w) flow += delta;           // forward edge\n        else throw new IllegalArgumentException(\"invalid endpoint\");\n\n        // round flow to 0 or capacity if within floating-point precision\n        if (Math.abs(flow) <= FLOATING_POINT_EPSILON)\n            flow = 0;\n        if (Math.abs(flow - capacity) <= FLOATING_POINT_EPSILON)\n            flow = capacity;\n\n        if (!(flow >= 0.0))      throw new IllegalArgumentException(\"Flow is negative\");\n        if (!(flow <= capacity)) throw new IllegalArgumentException(\"Flow exceeds capacity\");\n    }\n\n\n    /**\n     * Returns a string representation of the edge.\n     * @return a string representation of the edge\n     */\n    public String toString() {\n        return v + \"->\" + w + \" \" + flow + \"/\" + capacity;\n    }\n\n\n   /**\n     * Unit tests the {@code FlowEdge} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        FlowEdge e = new FlowEdge(12, 23, 4.56);\n        StdOut.println(e);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FlowNetwork.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FlowNetwork.java\n *  Execution:    java FlowNetwork V E\n *  Dependencies: Bag.java FlowEdge.java\n *\n *  A capacitated flow network, implemented using adjacency lists.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code FlowNetwork} class represents a capacitated network\n *  with vertices named 0 through <em>V</em> - 1, where each directed\n *  edge is of type {@link FlowEdge} and has a real-valued capacity\n *  and flow.\n *  It supports the following two primary operations: add an edge to the network,\n *  iterate over all of the edges incident to or from a vertex. It also provides\n *  methods for returning the number of vertices <em>V</em> and the number\n *  of edges <em>E</em>. Parallel edges and self-loops are permitted.\n *  <p>\n *  This implementation uses an adjacency-lists representation, which\n *  is a vertex-indexed array of {@link Bag} objects.\n *  All operations take constant time (in the worst case) except\n *  iterating over the edges incident to a given vertex, which takes\n *  time proportional to the number of such edges.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/64maxflow\">Section 6.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FlowNetwork {\n    private static final String NEWLINE = System.getProperty(\"line.separator\");\n\n    private final int V;\n    private int E;\n    private Bag<FlowEdge>[] adj;\n\n    /**\n     * Initializes an empty flow network with {@code V} vertices and 0 edges.\n     * @param V the number of vertices\n     * @throws IllegalArgumentException if {@code V < 0}\n     */\n    public FlowNetwork(int V) {\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices in a Graph must be non-negative\");\n        this.V = V;\n        this.E = 0;\n        adj = (Bag<FlowEdge>[]) new Bag[V];\n        for (int v = 0; v < V; v++)\n            adj[v] = new Bag<FlowEdge>();\n    }\n\n    /**\n     * Initializes a random flow network with {@code V} vertices and <em>E</em> edges.\n     * The capacities are integers between 0 and 99 and the flow values are zero.\n     * @param V the number of vertices\n     * @param E the number of edges\n     * @throws IllegalArgumentException if {@code V < 0}\n     * @throws IllegalArgumentException if {@code E < 0}\n     */\n    public FlowNetwork(int V, int E) {\n        this(V);\n        if (E < 0) throw new IllegalArgumentException(\"Number of edges must be non-negative\");\n        for (int i = 0; i < E; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            double capacity = StdRandom.uniformInt(100);\n            addEdge(new FlowEdge(v, w, capacity));\n        }\n    }\n\n    /**\n     * Initializes a flow network from an input stream.\n     * The format is the number of vertices <em>V</em>,\n     * followed by the number of edges <em>E</em>,\n     * followed by <em>E</em> pairs of vertices and edge capacities,\n     * with each entry separated by whitespace.\n     * @param in the input stream\n     * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range\n     * @throws IllegalArgumentException if the number of vertices or edges is negative\n     */\n    public FlowNetwork(In in) {\n        this(in.readInt());\n        int E = in.readInt();\n        if (E < 0) throw new IllegalArgumentException(\"number of edges must be non-negative\");\n        for (int i = 0; i < E; i++) {\n            int v = in.readInt();\n            int w = in.readInt();\n            validateVertex(v);\n            validateVertex(w);\n            double capacity = in.readDouble();\n            addEdge(new FlowEdge(v, w, capacity));\n        }\n    }\n\n\n    /**\n     * Returns the number of vertices in the edge-weighted graph.\n     * @return the number of vertices in the edge-weighted graph\n     */\n    public int V() {\n        return V;\n    }\n\n    /**\n     * Returns the number of edges in the edge-weighted graph.\n     * @return the number of edges in the edge-weighted graph\n     */\n    public int E() {\n        return E;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Adds the edge {@code e} to the network.\n     * @param e the edge\n     * @throws IllegalArgumentException unless endpoints of edge are between\n     *         {@code 0} and {@code V-1}\n     */\n    public void addEdge(FlowEdge e) {\n        int v = e.from();\n        int w = e.to();\n        validateVertex(v);\n        validateVertex(w);\n        adj[v].add(e);\n        adj[w].add(e);\n        E++;\n    }\n\n    /**\n     * Returns the edges incident on vertex {@code v} (includes both edges pointing to\n     * and from {@code v}).\n     * @param v the vertex\n     * @return the edges incident on vertex {@code v} as an Iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<FlowEdge> adj(int v) {\n        validateVertex(v);\n        return adj[v];\n    }\n\n    // return list of all edges - excludes self loops\n    public Iterable<FlowEdge> edges() {\n        Bag<FlowEdge> list = new Bag<FlowEdge>();\n        for (int v = 0; v < V; v++)\n            for (FlowEdge e : adj(v)) {\n                if (e.to() != v)\n                    list.add(e);\n            }\n        return list;\n    }\n\n\n    /**\n     * Returns a string representation of the flow network.\n     * This method takes time proportional to <em>E</em> + <em>V</em>.\n     * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,\n     *    followed by the <em>V</em> adjacency lists\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(V + \" \" + E + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            s.append(v + \":  \");\n            for (FlowEdge e : adj[v]) {\n                if (e.to() != v) s.append(e + \"  \");\n            }\n            s.append(NEWLINE);\n        }\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code FlowNetwork} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        FlowNetwork G = new FlowNetwork(in);\n        StdOut.println(G);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FloydWarshall.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FloydWarshall.java\n *  Execution:    java FloydWarshall V E\n *  Dependencies: AdjMatrixEdgeWeightedDigraph.java\n *\n *  Floyd-Warshall all-pairs shortest path algorithm.\n *\n *  % java FloydWarshall 100 500\n *\n *  Should check for negative cycles during triple loop; otherwise\n *  intermediate numbers can get exponentially large.\n *  Reference: \"The Floyd-Warshall algorithm on graphs with negative cycles\"\n *  by Stefan Hougardy\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code FloydWarshall} class represents a data type for solving the\n *  all-pairs shortest paths problem in edge-weighted digraphs with\n *  no negative cycles.\n *  The edge weights can be positive, negative, or zero.\n *  This class finds either a shortest path between every pair of vertices\n *  or a negative cycle.\n *  <p>\n *  This implementation uses the Floyd-Warshall algorithm.\n *  The constructor takes &Theta;(<em>V</em><sup>3</sup>) time,\n *  where <em>V</em> is the number of vertices.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em><sup>2</sup>) extra space\n *  (not including the edge-weighted digraph).\n *  <p>\n *  This correctly computes shortest paths if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  This is the case if all edge weights are integers and if none of the\n *  intermediate results exceeds 2<sup>52</sup>. Since all intermediate\n *  results are sums of edge weights, they are bounded by <em>V C</em>,\n *  where <em>V</em> is the number of vertices and <em>C</em> is the maximum\n *  absolute value of any edge weight.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/44sp\">Section 4.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FloydWarshall {\n    private boolean hasNegativeCycle;  // is there a negative cycle?\n    private double[][] distTo;         // distTo[v][w] = length of shortest v->w path\n    private DirectedEdge[][] edgeTo;   // edgeTo[v][w] = last edge on shortest v->w path\n\n    /**\n     * Computes a shortest paths tree from each vertex to every other vertex in\n     * the edge-weighted digraph {@code G}. If no such shortest path exists for\n     * some pair of vertices, it computes a negative cycle.\n     * @param G the edge-weighted digraph\n     */\n    public FloydWarshall(AdjMatrixEdgeWeightedDigraph G) {\n        int V = G.V();\n        distTo = new double[V][V];\n        edgeTo = new DirectedEdge[V][V];\n\n        // initialize distances to infinity\n        for (int v = 0; v < V; v++) {\n            for (int w = 0; w < V; w++) {\n                distTo[v][w] = Double.POSITIVE_INFINITY;\n            }\n        }\n\n        // initialize distances using edge-weighted digraph's\n        for (int v = 0; v < G.V(); v++) {\n            for (DirectedEdge e : G.adj(v)) {\n                distTo[e.from()][e.to()] = e.weight();\n                edgeTo[e.from()][e.to()] = e;\n            }\n            // in case of self-loops\n            if (distTo[v][v] >= 0.0) {\n                distTo[v][v] = 0.0;\n                edgeTo[v][v] = null;\n            }\n        }\n\n        // Floyd-Warshall updates\n        for (int i = 0; i < V; i++) {\n            // compute shortest paths using only 0, 1, ..., i as intermediate vertices\n            for (int v = 0; v < V; v++) {\n                if (edgeTo[v][i] == null) continue;  // optimization\n                for (int w = 0; w < V; w++) {\n                    if (distTo[v][w] > distTo[v][i] + distTo[i][w]) {\n                        distTo[v][w] = distTo[v][i] + distTo[i][w];\n                        edgeTo[v][w] = edgeTo[i][w];\n                    }\n                }\n                // check for negative cycle\n                if (distTo[v][v] < 0.0) {\n                    hasNegativeCycle = true;\n                    return;\n                }\n            }\n        }\n        assert check(G);\n    }\n\n    /**\n     * Is there a negative cycle?\n     * @return {@code true} if there is a negative cycle, and {@code false} otherwise\n     */\n    public boolean hasNegativeCycle() {\n        return hasNegativeCycle;\n    }\n\n    /**\n     * Returns a negative cycle, or {@code null} if there is no such cycle.\n     * @return a negative cycle as an iterable of edges,\n     * or {@code null} if there is no such cycle\n     */\n    public Iterable<DirectedEdge> negativeCycle() {\n        for (int v = 0; v < distTo.length; v++) {\n            // negative cycle in v's predecessor graph\n            if (distTo[v][v] < 0.0) {\n                int V = edgeTo.length;\n                EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V);\n                for (int w = 0; w < V; w++)\n                    if (edgeTo[v][w] != null)\n                        spt.addEdge(edgeTo[v][w]);\n                EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt);\n                assert finder.hasCycle();\n                return finder.cycle();\n            }\n        }\n        return null;\n    }\n\n    /**\n     * Is there a path from the vertex {@code s} to vertex {@code t}?\n     * @param  s the source vertex\n     * @param  t the destination vertex\n     * @return {@code true} if there is a path from vertex {@code s}\n     *         to vertex {@code t}, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     * @throws IllegalArgumentException unless {@code 0 <= t < V}\n     */\n    public boolean hasPath(int s, int t) {\n        validateVertex(s);\n        validateVertex(t);\n        return distTo[s][t] < Double.POSITIVE_INFINITY;\n    }\n\n    /**\n     * Returns the length of a shortest path from vertex {@code s} to vertex {@code t}.\n     * @param  s the source vertex\n     * @param  t the destination vertex\n     * @return the length of a shortest path from vertex {@code s} to vertex {@code t};\n     *         {@code Double.POSITIVE_INFINITY} if no such path\n     * @throws UnsupportedOperationException if there is a negative cost cycle\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public double dist(int s, int t) {\n        validateVertex(s);\n        validateVertex(t);\n        if (hasNegativeCycle())\n            throw new UnsupportedOperationException(\"Negative cost cycle exists\");\n        return distTo[s][t];\n    }\n\n    /**\n     * Returns a shortest path from vertex {@code s} to vertex {@code t}.\n     * @param  s the source vertex\n     * @param  t the destination vertex\n     * @return a shortest path from vertex {@code s} to vertex {@code t}\n     *         as an iterable of edges, and {@code null} if no such path\n     * @throws UnsupportedOperationException if there is a negative cost cycle\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<DirectedEdge> path(int s, int t) {\n        validateVertex(s);\n        validateVertex(t);\n        if (hasNegativeCycle())\n            throw new UnsupportedOperationException(\"Negative cost cycle exists\");\n        if (!hasPath(s, t)) return null;\n        Stack<DirectedEdge> path = new Stack<DirectedEdge>();\n        for (DirectedEdge e = edgeTo[s][t]; e != null; e = edgeTo[s][e.from()]) {\n            path.push(e);\n        }\n        return path;\n    }\n\n    // check optimality conditions\n    private boolean check(AdjMatrixEdgeWeightedDigraph G) {\n\n        // no negative cycle\n        if (!hasNegativeCycle()) {\n            for (int v = 0; v < G.V(); v++) {\n                for (DirectedEdge e : G.adj(v)) {\n                    int w = e.to();\n                    for (int i = 0; i < G.V(); i++) {\n                        if (distTo[i][w] > distTo[i][v] + e.weight()) {\n                            System.err.println(\"edge \" + e + \" is eligible\");\n                            return false;\n                        }\n                    }\n                }\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = distTo.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code FloydWarshall} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // random graph with V vertices and E edges, parallel edges allowed\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        AdjMatrixEdgeWeightedDigraph G = new AdjMatrixEdgeWeightedDigraph(V);\n        for (int i = 0; i < E; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            double weight = 0.01 * StdRandom.uniformInt(-15, 100);\n            if (v == w) G.addEdge(new DirectedEdge(v, w, Math.abs(weight)));\n            else G.addEdge(new DirectedEdge(v, w, weight));\n        }\n\n        StdOut.println(G);\n\n        // run Floyd-Warshall algorithm\n        FloydWarshall spt = new FloydWarshall(G);\n\n        // print all-pairs shortest path distances\n        StdOut.printf(\"  \");\n        for (int v = 0; v < G.V(); v++) {\n            StdOut.printf(\"%6d \", v);\n        }\n        StdOut.println();\n        for (int v = 0; v < G.V(); v++) {\n            StdOut.printf(\"%3d: \", v);\n            for (int w = 0; w < G.V(); w++) {\n                if (spt.hasPath(v, w)) StdOut.printf(\"%6.2f \", spt.dist(v, w));\n                else StdOut.printf(\"  Inf \");\n            }\n            StdOut.println();\n        }\n\n        // print negative cycle\n        if (spt.hasNegativeCycle()) {\n            StdOut.println(\"Negative cost cycle:\");\n            for (DirectedEdge e : spt.negativeCycle())\n                StdOut.println(e);\n            StdOut.println();\n        }\n\n        // print all-pairs shortest paths\n        else {\n            for (int v = 0; v < G.V(); v++) {\n                for (int w = 0; w < G.V(); w++) {\n                    if (spt.hasPath(v, w)) {\n                        StdOut.printf(\"%d to %d (%5.2f)  \", v, w, spt.dist(v, w));\n                        for (DirectedEdge e : spt.path(v, w))\n                            StdOut.print(e + \"  \");\n                        StdOut.println();\n                    }\n                    else {\n                        StdOut.printf(\"%d to %d no path\\n\", v, w);\n                    }\n                }\n            }\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FordFulkerson.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FordFulkerson.java\n *  Execution:    java FordFulkerson V E\n *  Dependencies: FlowNetwork.java FlowEdge.java Queue.java\n *  Data files:   https://algs4.cs.princeton.edu/65maxflow/tinyFN.txt\n *\n *  Ford-Fulkerson algorithm for computing a max flow and\n *  a min cut using shortest augmenting path rule.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code FordFulkerson} class represents a data type for computing a\n *  <em>maximum st-flow</em> and <em>minimum st-cut</em> in a flow\n *  network.\n *  <p>\n *  This implementation uses the <em>Ford-Fulkerson</em> algorithm with\n *  the <em>shortest augmenting path</em> heuristic.\n *  The constructor takes <em>O</em>(<em>E V</em> (<em>E</em> + <em>V</em>))\n *  time, where <em>V</em> is the number of vertices and <em>E</em> is\n *  the number of edges. In practice, the algorithm will run much faster.\n *  The {@code inCut()} and {@code value()} methods take &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the network).\n *  <p>\n *  This correctly computes the maxflow and mincut if all arithmetic\n *  performed is without floating-point rounding error or arithmetic\n *  overflow. This is guaranteed to be the case if all edge capacities\n *  and initial flow values are integers and the value of the maxflow\n *  does not exceed 2<sup>52</sup>.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/64maxflow\">Section 6.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FordFulkerson {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-11;\n\n    private final int V;          // number of vertices\n    private boolean[] marked;     // marked[v] = true iff s->v path in residual graph\n    private FlowEdge[] edgeTo;    // edgeTo[v] = last edge on shortest residual s->v path\n    private double value;         // current value of max flow\n\n    /**\n     * Compute a maximum flow and minimum cut in the network {@code G}\n     * from vertex {@code s} to vertex {@code t}.\n     *\n     * @param  G the flow network\n     * @param  s the source vertex\n     * @param  t the sink vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     * @throws IllegalArgumentException unless {@code 0 <= t < V}\n     * @throws IllegalArgumentException if {@code s == t}\n     * @throws IllegalArgumentException if initial flow is infeasible\n     */\n    public FordFulkerson(FlowNetwork G, int s, int t) {\n        V = G.V();\n        validate(s);\n        validate(t);\n        if (s == t)               throw new IllegalArgumentException(\"Source equals sink\");\n        if (!isFeasible(G, s, t)) throw new IllegalArgumentException(\"Initial flow is infeasible\");\n\n        // while there exists an augmenting path, use it\n        value = excess(G, t);\n        while (hasAugmentingPath(G, s, t)) {\n\n            // compute bottleneck capacity\n            double bottle = Double.POSITIVE_INFINITY;\n            for (int v = t; v != s; v = edgeTo[v].other(v)) {\n                bottle = Math.min(bottle, edgeTo[v].residualCapacityTo(v));\n            }\n\n            // augment flow\n            for (int v = t; v != s; v = edgeTo[v].other(v)) {\n                edgeTo[v].addResidualFlowTo(v, bottle);\n            }\n\n            value += bottle;\n        }\n\n        // check optimality conditions\n        assert check(G, s, t);\n    }\n\n    /**\n     * Returns the value of the maximum flow.\n     *\n     * @return the value of the maximum flow\n     */\n    public double value()  {\n        return value;\n    }\n\n    /**\n     * Returns true if the specified vertex is on the {@code s} side of the mincut.\n     *\n     * @param  v vertex\n     * @return {@code true} if vertex {@code v} is on the {@code s} side of the mincut;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean inCut(int v)  {\n        validate(v);\n        return marked[v];\n    }\n\n    // throw an IllegalArgumentException if v is outside prescribed range\n    private void validate(int v)  {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n\n    // is there an augmenting path?\n    // if so, upon termination edgeTo[] will contain a parent-link representation of such a path\n    // this implementation finds a shortest augmenting path (fewest number of edges),\n    // which performs well both in theory and in practice\n    private boolean hasAugmentingPath(FlowNetwork G, int s, int t) {\n        edgeTo = new FlowEdge[G.V()];\n        marked = new boolean[G.V()];\n\n        // breadth-first search\n        Queue<Integer> queue = new Queue<Integer>();\n        queue.enqueue(s);\n        marked[s] = true;\n        while (!queue.isEmpty() && !marked[t]) {\n            int v = queue.dequeue();\n\n            for (FlowEdge e : G.adj(v)) {\n                int w = e.other(v);\n\n                // if residual capacity from v to w\n                if (e.residualCapacityTo(w) > 0) {\n                    if (!marked[w]) {\n                        edgeTo[w] = e;\n                        marked[w] = true;\n                        queue.enqueue(w);\n                    }\n                }\n            }\n        }\n\n        // is there an augmenting path?\n        return marked[t];\n    }\n\n\n\n    // return excess flow at vertex v\n    private double excess(FlowNetwork G, int v) {\n        double excess = 0.0;\n        for (FlowEdge e : G.adj(v)) {\n            if (v == e.from()) excess -= e.flow();\n            else               excess += e.flow();\n        }\n        return excess;\n    }\n\n    // return excess flow at vertex v\n    private boolean isFeasible(FlowNetwork G, int s, int t) {\n\n        // check that capacity constraints are satisfied\n        for (int v = 0; v < G.V(); v++) {\n            for (FlowEdge e : G.adj(v)) {\n                if (e.flow() < -FLOATING_POINT_EPSILON || e.flow() > e.capacity() + FLOATING_POINT_EPSILON) {\n                    System.err.println(\"Edge does not satisfy capacity constraints: \" + e);\n                    return false;\n                }\n            }\n        }\n\n        // check that net flow into a vertex equals zero, except at source and sink\n        if (Math.abs(value + excess(G, s)) > FLOATING_POINT_EPSILON) {\n            System.err.println(\"Excess at source = \" + excess(G, s));\n            System.err.println(\"Max flow         = \" + value);\n            return false;\n        }\n        if (Math.abs(value - excess(G, t)) > FLOATING_POINT_EPSILON) {\n            System.err.println(\"Excess at sink   = \" + excess(G, t));\n            System.err.println(\"Max flow         = \" + value);\n            return false;\n        }\n        for (int v = 0; v < G.V(); v++) {\n            if (v == s || v == t) continue;\n            else if (Math.abs(excess(G, v)) > FLOATING_POINT_EPSILON) {\n                System.err.println(\"Net flow out of \" + v + \" doesn't equal zero\");\n                return false;\n            }\n        }\n        return true;\n    }\n\n\n\n    // check optimality conditions\n    private boolean check(FlowNetwork G, int s, int t) {\n\n        // check that flow is feasible\n        if (!isFeasible(G, s, t)) {\n            System.err.println(\"Flow is infeasible\");\n            return false;\n        }\n\n        // check that s is on the source side of min cut and that t is not on source side\n        if (!inCut(s)) {\n            System.err.println(\"source \" + s + \" is not on source side of min cut\");\n            return false;\n        }\n        if (inCut(t)) {\n            System.err.println(\"sink \" + t + \" is on source side of min cut\");\n            return false;\n        }\n\n        // check that value of min cut = value of max flow\n        double mincutValue = 0.0;\n        for (int v = 0; v < G.V(); v++) {\n            for (FlowEdge e : G.adj(v)) {\n                if ((v == e.from()) && inCut(e.from()) && !inCut(e.to()))\n                    mincutValue += e.capacity();\n            }\n        }\n\n        if (Math.abs(mincutValue - value) > FLOATING_POINT_EPSILON) {\n            System.err.println(\"Max flow value = \" + value + \", min cut value = \" + mincutValue);\n            return false;\n        }\n\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code FordFulkerson} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // create flow network with V vertices and E edges\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        int s = 0, t = V-1;\n        FlowNetwork G = new FlowNetwork(V, E);\n        StdOut.println(G);\n\n        // compute maximum flow and minimum cut\n        FordFulkerson maxflow = new FordFulkerson(G, s, t);\n        StdOut.println(\"Max flow from \" + s + \" to \" + t);\n        for (int v = 0; v < G.V(); v++) {\n            for (FlowEdge e : G.adj(v)) {\n                if ((v == e.from()) && e.flow() > 0)\n                    StdOut.println(\"   \" + e);\n            }\n        }\n\n        // print min-cut\n        StdOut.print(\"Min cut: \");\n        for (int v = 0; v < G.V(); v++) {\n            if (maxflow.inCut(v)) StdOut.print(v + \" \");\n        }\n        StdOut.println();\n\n        StdOut.println(\"Max flow value = \" +  maxflow.value());\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/FrequencyCounter.java",
    "content": "/******************************************************************************\n *  Compilation:  javac FrequencyCounter.java\n *  Execution:    java FrequencyCounter L < input.txt\n *  Dependencies: ST.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/31elementary/tinyTale.txt\n *                https://algs4.cs.princeton.edu/31elementary/tale.txt\n *                https://algs4.cs.princeton.edu/31elementary/leipzig100K.txt\n *                https://algs4.cs.princeton.edu/31elementary/leipzig300K.txt\n *                https://algs4.cs.princeton.edu/31elementary/leipzig1M.txt\n *\n *  Read in a list of words from standard input and print out\n *  the most frequently occurring word that has length greater than\n *  a given threshold.\n *\n *  % java FrequencyCounter 1 < tinyTale.txt\n *  it 10\n *\n *  % java FrequencyCounter 8 < tale.txt\n *  business 122\n *\n *  % java FrequencyCounter 10 < leipzig1M.txt\n *  government 24763\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code FrequencyCounter} class provides a client for\n *  reading in a sequence of words and printing a word (exceeding\n *  a given length) that occurs most frequently. It is useful as\n *  a test client for various symbol table implementations.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/31elementary\">Section 3.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class FrequencyCounter {\n\n    // Do not instantiate.\n    private FrequencyCounter() { }\n\n    /**\n     * Reads in a command-line integer and sequence of words from\n     * standard input and prints out a word (whose length exceeds\n     * the threshold) that occurs most frequently to standard output.\n     * It also prints out the number of words whose length exceeds\n     * the threshold and the number of distinct such words.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int distinct = 0, words = 0;\n        int minlen = Integer.parseInt(args[0]);\n        ST<String, Integer> st = new ST<String, Integer>();\n\n        // compute frequency counts\n        while (!StdIn.isEmpty()) {\n            String key = StdIn.readString();\n            if (key.length() < minlen) continue;\n            words++;\n            if (st.contains(key)) {\n                st.put(key, st.get(key) + 1);\n            }\n            else {\n                st.put(key, 1);\n                distinct++;\n            }\n        }\n\n        // find a key with the highest frequency count\n        String max = \"\";\n        st.put(max, 0);\n        for (String word : st.keys()) {\n            if (st.get(word) > st.get(max))\n                max = word;\n        }\n\n        StdOut.println(max + \" \" + st.get(max));\n        StdOut.println(\"distinct = \" + distinct);\n        StdOut.println(\"words    = \" + words);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GREP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GREP.java\n *  Execution:    java GREP regexp < input.txt\n *  Dependencies: NFA.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/54regexp/tinyL.txt\n *\n *  This program takes an RE as a command-line argument and prints\n *  the lines from standard input having some substring that\n *  is in the language described by the RE.\n *\n *  % more tinyL.txt\n *  AC\n *  AD\n *  AAA\n *  ABD\n *  ADD\n *  BCD\n *  ABCCBD\n *  BABAAA\n *  BABBAAA\n *\n *  %  java GREP \"(A*B|AC)D\" < tinyL.txt\n *  ABD\n *  ABCCBD\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code GREP} class provides a client for reading in a sequence of\n *  lines from standard input and printing to standard output those lines\n *  that contain a substring matching a specified regular expression.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/31elementary\">Section 3.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class GREP {\n\n    // do not instantiate\n    private GREP() { }\n\n    /**\n     * Interprets the command-line argument as a regular expression\n     * (supporting closure, binary or, parentheses, and wildcard)\n     * reads in lines from standard input; writes to standard output\n     * those lines that contain a substring matching the regular\n     * expression.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String regexp = \"(.*\" + args[0] + \".*)\";\n        NFA nfa = new NFA(regexp);\n        while (StdIn.hasNextLine()) {\n            String line = StdIn.readLine();\n            if (nfa.recognizes(line)) {\n                StdOut.println(line);\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GabowSCC.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GabowSCC.java\n *  Execution:    java GabowSCC V E\n *  Dependencies: Digraph.java Stack.java TransitiveClosure.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Compute the strongly-connected components of a digraph using\n *  Gabow's algorithm (aka Cheriyan-Mehlhorn algorithm).\n *\n *  Runs in O(E + V) time.\n *\n *  % java GabowSCC tinyDG.txt\n *  5 components\n *  1\n *  0 2 3 4 5\n *  9 10 11 12\n *  6 8\n *  7\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n/**\n *  The {@code GabowSCC} class represents a data type for\n *  determining the strong components in a digraph.\n *  The <em>id</em> operation determines in which strong component\n *  a given vertex lies; the <em>areStronglyConnected</em> operation\n *  determines whether two vertices are in the same strong component;\n *  and the <em>count</em> operation determines the number of strong\n *  components.\n *  <p>\n *  The <em>component identifier</em> of a vertex is an integer between\n *  0 and <em>k</em>–1, where <em>k</em> is the number of strong components.\n *  Two vertices have the same component identifier if and only if they\n *  are in the same strong component.\n *  <p>\n *  This implementation uses the Gabow's algorithm.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time,\n *  where <em>V</em> is the number of vertices and <em>E</em> is\n *  the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  For alternative implementations of the same API, see\n *  {@link KosarajuSharirSCC} and {@link TarjanSCC}.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class GabowSCC {\n\n    private boolean[] marked;        // marked[v] = has v been visited?\n    private int[] id;                // id[v] = id of strong component containing v\n    private int[] preorder;          // preorder[v] = preorder of v\n    private int pre;                 // preorder number counter\n    private int count;               // number of strongly-connected components\n    private Stack<Integer> stack1;\n    private Stack<Integer> stack2;\n\n\n    /**\n     * Computes the strong components in a digraph.\n     * @param digraph the digraph\n     */\n    public GabowSCC(Digraph digraph) {\n        marked = new boolean[digraph.V()];\n        stack1 = new Stack<Integer>();\n        stack2 = new Stack<Integer>();\n        id = new int[digraph.V()];\n        preorder = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            id[v] = -1;\n\n        for (int v = 0; v < digraph.V(); v++) {\n            if (!marked[v]) dfs(digraph, v);\n        }\n\n        // check that id[] gives strong components\n        assert check(digraph);\n    }\n\n    private void dfs(Digraph digraph, int v) {\n        marked[v] = true;\n        preorder[v] = pre++;\n        stack1.push(v);\n        stack2.push(v);\n        for (int w : digraph.adj(v)) {\n            if (!marked[w]) dfs(digraph, w);\n            else if (id[w] == -1) {\n                while (preorder[stack2.peek()] > preorder[w])\n                    stack2.pop();\n            }\n        }\n\n        // found strong component containing v\n        if (stack2.peek() == v) {\n            stack2.pop();\n            int w;\n            do {\n                w = stack1.pop();\n                id[w] = count;\n            } while (w != v);\n            count++;\n        }\n    }\n\n    /**\n     * Returns the number of strong components.\n     * @return the number of strong components\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Are vertices {@code v} and {@code w} in the same strong component?\n     * @param  v one vertex\n     * @param  w the other vertex\n     * @return {@code true} if vertices {@code v} and {@code w} are in the same\n     *         strong component, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws IllegalArgumentException unless {@code 0 <= w < V}\n     */\n    public boolean stronglyConnected(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        return id[v] == id[w];\n    }\n\n    /**\n     * Returns the component id of the strong component containing vertex {@code v}.\n     * @param  v the vertex\n     * @return the component id of the strong component containing vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int id(int v) {\n        validateVertex(v);\n        return id[v];\n    }\n\n    // does the id[] array contain the strongly connected components?\n    private boolean check(Digraph digraph) {\n        TransitiveClosure tc = new TransitiveClosure(digraph);\n        for (int v = 0; v < digraph.V(); v++) {\n            for (int w = 0; w < digraph.V(); w++) {\n                if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v)))\n                    return false;\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code GabowSCC} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n        GabowSCC scc = new GabowSCC(digraph);\n\n        // number of connected components\n        int m = scc.count();\n        StdOut.println(m + \" components\");\n\n        // compute list of vertices in each strong component\n        Queue<Integer>[] components = (Queue<Integer>[]) new Queue[m];\n        for (int i = 0; i < m; i++) {\n            components[i] = new Queue<Integer>();\n        }\n        for (int v = 0; v < digraph.V(); v++) {\n            components[scc.id(v)].enqueue(v);\n        }\n\n        // print results\n        for (int i = 0; i < m; i++) {\n            for (int v : components[i]) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GaussJordanElimination.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GaussJordanElimination.java\n *  Execution:    java GaussJordanElimination n\n *  Dependencies: StdOut.java\n *\n *  Finds a solutions to Ax = b using Gauss-Jordan elimination with partial\n *  pivoting. If no solution exists, find a solution to yA = 0, yb != 0,\n *  which serves as a certificate of infeasibility.\n *\n *  % java GaussJordanElimination\n *  -1.000000\n *  2.000000\n *  2.000000\n *\n *  3.000000\n *  -1.000000\n *  -2.000000\n *\n *  System is infeasible\n *\n *  -6.250000\n *  -4.500000\n *  0.000000\n *  0.000000\n *  1.000000\n *\n *  System is infeasible\n *\n *  -1.375000\n *  1.625000\n *  0.000000\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code GaussJordanElimination} data type provides methods\n *  to solve a linear system of equations <em>Ax</em> = <em>b</em>,\n *  where <em>A</em> is an <em>n</em>-by-<em>n</em> matrix\n *  and <em>b</em> is a length <em>n</em> vector.\n *  If no solution exists, it finds a solution <em>y</em> to\n *  <em>yA</em> = 0, <em>yb</em> &ne; 0,\n *  which serves as a certificate of infeasibility.\n *  <p>\n *  This implementation uses Gauss-Jordan elimination with partial pivoting.\n *  See {@link GaussianElimination} for an implementation that uses\n *  Gaussian elimination (but does not provide the certificate of infeasibility).\n *  For an industrial-strength numerical linear algebra library,\n *  see <a href = \"http://math.nist.gov/javanumerics/jama/\">JAMA</a>.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  In practice, there will be floating-point rounding error;\n *  partial pivoting helps prevent accumulated floating-point rounding\n *  errors from growing out of control (though it does not\n *  provide any guarantees).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/99scientific\">Section 9.9</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class GaussJordanElimination {\n    private static final double EPSILON = 1e-8;\n\n    private final int n;      // n-by-n system\n    private double[][] a;     // n-by-(n+1) augmented matrix\n\n    // Gauss-Jordan elimination with partial pivoting\n    /**\n     * Solves the linear system of equations <em>Ax</em> = <em>b</em>,\n     * where <em>A</em> is an <em>n</em>-by-<em>n</em> matrix and <em>b</em>\n     * is a length <em>n</em> vector.\n     *\n     * @param  A the <em>n</em>-by-<em>n</em> constraint matrix\n     * @param  b the length <em>n</em> right-hand-side vector\n     */\n    public GaussJordanElimination(double[][] A, double[] b) {\n        n = b.length;\n\n        // build augmented matrix\n        a = new double[n][n+n+1];\n        for (int i = 0; i < n; i++)\n            for (int j = 0; j < n; j++)\n                a[i][j] = A[i][j];\n\n        // only needed if you want to find certificate of infeasibility (or compute inverse)\n        for (int i = 0; i < n; i++)\n            a[i][n+i] = 1.0;\n\n        for (int i = 0; i < n; i++)\n            a[i][n+n] = b[i];\n\n        solve();\n\n        assert certifySolution(A, b);\n    }\n\n    private void solve() {\n\n        // Gauss-Jordan elimination\n        for (int p = 0; p < n; p++) {\n            // show();\n\n            // find pivot row using partial pivoting\n            int max = p;\n            for (int i = p+1; i < n; i++) {\n                if (Math.abs(a[i][p]) > Math.abs(a[max][p])) {\n                    max = i;\n                }\n            }\n\n            // exchange row p with row max\n            swap(p, max);\n\n            // singular or nearly singular\n            if (Math.abs(a[p][p]) <= EPSILON) {\n                continue;\n                // throw new ArithmeticException(\"Matrix is singular or nearly singular\");\n            }\n\n            // pivot\n            pivot(p, p);\n        }\n        // show();\n    }\n\n    // swap row1 and row2\n    private void swap(int row1, int row2) {\n        double[] temp = a[row1];\n        a[row1] = a[row2];\n        a[row2] = temp;\n    }\n\n\n    // pivot on entry (p, q) using Gauss-Jordan elimination\n    private void pivot(int p, int q) {\n\n        // everything but row p and column q\n        for (int i = 0; i < n; i++) {\n            double alpha = a[i][q] / a[p][q];\n            for (int j = 0; j <= n+n; j++) {\n                if (i != p && j != q) a[i][j] -= alpha * a[p][j];\n            }\n        }\n\n        // zero out column q\n        for (int i = 0; i < n; i++)\n            if (i != p) a[i][q] = 0.0;\n\n        // scale row p (ok to go from q+1 to n, but do this for consistency with simplex pivot)\n        for (int j = 0; j <= n+n; j++)\n            if (j != q) a[p][j] /= a[p][q];\n        a[p][q] = 1.0;\n    }\n\n    /**\n     * Returns a solution to the linear system of equations <em>Ax</em> = <em>b</em>.\n     *\n     * @return a solution <em>x</em> to the linear system of equations\n     *         <em>Ax</em> = <em>b</em>; {@code null} if no such solution\n     */\n    public double[] primal() {\n        double[] x = new double[n];\n        for (int i = 0; i < n; i++) {\n            if (Math.abs(a[i][i]) > EPSILON)\n                x[i] = a[i][n+n] / a[i][i];\n            else if (Math.abs(a[i][n+n]) > EPSILON)\n                return null;\n        }\n        return x;\n    }\n\n    /**\n     * Returns a solution to the linear system of equations <em>yA</em> = 0,\n     * <em>yb</em> &ne; 0.\n     *\n     * @return a solution <em>y</em> to the linear system of equations\n     *         <em>yA</em> = 0, <em>yb</em> &ne; 0; {@code null} if no such solution\n     */\n    public double[] dual() {\n        double[] y = new double[n];\n        for (int i = 0; i < n; i++) {\n            if ((Math.abs(a[i][i]) <= EPSILON) && (Math.abs(a[i][n+n]) > EPSILON)) {\n                for (int j = 0; j < n; j++)\n                    y[j] = a[i][n+j];\n                return y;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * Returns true if there exists a solution to the linear system of\n     * equations <em>Ax</em> = <em>b</em>.\n     *\n     * @return {@code true} if there exists a solution to the linear system\n     *         of equations <em>Ax</em> = <em>b</em>; {@code false} otherwise\n     */\n    public boolean isFeasible() {\n        return primal() != null;\n    }\n\n    // print the tableaux\n    private void show() {\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                StdOut.printf(\"%8.3f \", a[i][j]);\n            }\n            StdOut.printf(\"| \");\n            for (int j = n; j < n+n; j++) {\n                StdOut.printf(\"%8.3f \", a[i][j]);\n            }\n            StdOut.printf(\"| %8.3f\\n\", a[i][n+n]);\n        }\n        StdOut.println();\n    }\n\n\n    // check that Ax = b or yA = 0, yb != 0\n    private boolean certifySolution(double[][] A, double[] b) {\n\n        // check that Ax = b\n        if (isFeasible()) {\n            double[] x = primal();\n            for (int i = 0; i < n; i++) {\n                double sum = 0.0;\n                for (int j = 0; j < n; j++) {\n                    sum += A[i][j] * x[j];\n                }\n                if (Math.abs(sum - b[i]) > EPSILON) {\n                    StdOut.println(\"not feasible\");\n                    StdOut.printf(\"b[%d] = %8.3f, sum = %8.3f\\n\", i, b[i], sum);\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        // or that yA = 0, yb != 0\n        else {\n            double[] y = dual();\n            for (int j = 0; j < n; j++) {\n                double sum = 0.0;\n                for (int i = 0; i < n; i++) {\n                    sum += A[i][j] * y[i];\n                }\n                if (Math.abs(sum) > EPSILON) {\n                    StdOut.println(\"invalid certificate of infeasibility\");\n                    StdOut.printf(\"sum = %8.3f\\n\", sum);\n                    return false;\n                }\n            }\n            double sum = 0.0;\n            for (int i = 0; i < n; i++) {\n                sum += y[i] * b[i];\n            }\n            if (Math.abs(sum) < EPSILON) {\n                StdOut.println(\"invalid certificate of infeasibility\");\n                StdOut.printf(\"yb  = %8.3f\\n\", sum);\n                return false;\n            }\n            return true;\n        }\n    }\n\n\n    private static void test(String name, double[][] A, double[] b) {\n        StdOut.println(\"----------------------------------------------------\");\n        StdOut.println(name);\n        StdOut.println(\"----------------------------------------------------\");\n        GaussJordanElimination gaussian = new GaussJordanElimination(A, b);\n        if (gaussian.isFeasible()) {\n            StdOut.println(\"Solution to Ax = b\");\n            double[] x = gaussian.primal();\n            for (int i = 0; i < x.length; i++) {\n                StdOut.printf(\"%10.6f\\n\", x[i]);\n            }\n        }\n        else {\n            StdOut.println(\"Certificate of infeasibility\");\n            double[] y = gaussian.dual();\n            for (int j = 0; j < y.length; j++) {\n                StdOut.printf(\"%10.6f\\n\", y[j]);\n            }\n        }\n        StdOut.println();\n        StdOut.println();\n    }\n\n\n    // 3-by-3 nonsingular system\n    private static void test1() {\n        double[][] A = {\n            { 0, 1,  1 },\n            { 2, 4, -2 },\n            { 0, 3, 15 }\n        };\n        double[] b = { 4, 2, 36 };\n        test(\"test 1\", A, b);\n    }\n\n    // 3-by-3 nonsingular system\n    private static void test2() {\n        double[][] A = {\n            {  1, -3,   1 },\n            {  2, -8,   8 },\n            { -6,  3, -15 }\n        };\n        double[] b = { 4, -2, 9 };\n        test(\"test 2\", A, b);\n    }\n\n    // 5-by-5 singular: no solutions\n    // y = [ -1, 0, 1, 1, 0 ]\n    private static void test3() {\n        double[][] A = {\n            {  2, -3, -1,  2,  3 },\n            {  4, -4, -1,  4, 11 },\n            {  2, -5, -2,  2, -1 },\n            {  0,  2,  1,  0,  4 },\n            { -4,  6,  0,  0,  7 },\n        };\n        double[] b = { 4, 4, 9, -6, 5 };\n        test(\"test 3\", A, b);\n    }\n\n    // 5-by-5 singular: infinitely many solutions\n    private static void test4() {\n        double[][] A = {\n            {  2, -3, -1,  2,  3 },\n            {  4, -4, -1,  4, 11 },\n            {  2, -5, -2,  2, -1 },\n            {  0,  2,  1,  0,  4 },\n            { -4,  6,  0,  0,  7 },\n        };\n        double[] b = { 4, 4, 9, -5, 5 };\n        test(\"test 4\", A, b);\n    }\n\n    // 3-by-3 singular: no solutions\n    // y = [ 1, 0, 1/3 ]\n    private static void test5() {\n        double[][] A = {\n            {  2, -1,  1 },\n            {  3,  2, -4 },\n            { -6,  3, -3 },\n        };\n        double[] b = { 1, 4, 2 };\n        test(\"test 5\", A, b);\n    }\n\n    // 3-by-3 singular: infinitely many solutions\n    private static void test6() {\n        double[][] A = {\n            {  1, -1,  2 },\n            {  4,  4, -2 },\n            { -2,  2, -4 },\n        };\n        double[] b = { -3, 1, 6 };\n        test(\"test 6 (infinitely many solutions)\", A, b);\n    }\n\n    /**\n     * Unit tests the {@code GaussJordanElimination} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        test1();\n        test2();\n        test3();\n        test4();\n        test5();\n        test6();\n\n        // n-by-n random system (likely full rank)\n        int n = Integer.parseInt(args[0]);\n        double[][] A = new double[n][n];\n        for (int i = 0; i < n; i++)\n            for (int j = 0; j < n; j++)\n                A[i][j] = StdRandom.uniformInt(1000);\n        double[] b = new double[n];\n        for (int i = 0; i < n; i++)\n            b[i] = StdRandom.uniformInt(1000);\n        test(\"random \" + n + \"-by-\" + n + \" (likely full rank)\", A, b);\n\n\n        // n-by-n random system (likely infeasible)\n        A = new double[n][n];\n        for (int i = 0; i < n-1; i++)\n            for (int j = 0; j < n; j++)\n                A[i][j] = StdRandom.uniformInt(1000);\n        for (int i = 0; i < n-1; i++) {\n            double alpha = StdRandom.uniformInt(-5, 5);\n            for (int j = 0; j < n; j++) {\n                A[n-1][j] += alpha * A[i][j];\n            }\n        }\n        b = new double[n];\n        for (int i = 0; i < n; i++)\n            b[i] = StdRandom.uniformInt(1000);\n        test(\"random \" + n + \"-by-\" + n + \" (likely infeasible)\", A, b);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GaussianElimination.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GaussianElimination.java\n *  Execution:    java GaussianElimination m n\n *  Dependencies: StdOut.java\n *\n *  Gaussian elimination with partial pivoting for m-by-n system.\n *\n *  % java GaussianElimination m n\n *  -1.000000\n *  2.000000\n *  2.000000\n *\n *  3.000000\n *  -1.000000\n *  -2.000000\n *\n *  System is infeasible\n *\n *  -6.250000\n *  -4.500000\n *  0.000000\n *  0.000000\n *  1.000000\n *\n *  System is infeasible\n *\n *  -1.375000\n *  1.625000\n *  0.000000\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code GaussianElimination} data type provides methods\n *  to solve a linear system of equations <em>Ax</em> = <em>b</em>,\n *  where <em>A</em> is an <em>m</em>-by-<em>n</em> matrix\n *  and <em>b</em> is a length <em>n</em> vector.\n *  <p>\n *  This is a bare-bones implementation that uses Gaussian elimination\n *  with partial pivoting.\n *  See <a href = \"https://algs4.cs.princeton.edu/99scientific/GaussianEliminationLite.java.html\">GaussianEliminationLite.java</a>\n *  for a stripped-down version that assumes the matrix <em>A</em> is square\n *  and nonsingular. See {@link GaussJordanElimination} for an alternate\n *  implementation that uses Gauss-Jordan elimination.\n *  For an industrial-strength numerical linear algebra library,\n *  see <a href = \"http://math.nist.gov/javanumerics/jama/\">JAMA</a>.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  In practice, there will be floating-point rounding error;\n *  partial pivoting helps prevent accumulated floating-point rounding\n *  errors from growing out of control (though it does not\n *  provide any guarantees).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/99scientific\">Section 9.9</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class GaussianElimination {\n    private static final double EPSILON = 1.0E-8;\n\n    private final int m;      // number of rows\n    private final int n;      // number of columns\n    private double[][] a;     // m-by-(n+1) augmented matrix\n\n    /**\n     * Solves the linear system of equations <em>Ax</em> = <em>b</em>,\n     * where <em>A</em> is an <em>m</em>-by-<em>n</em> matrix and <em>b</em>\n     * is a length <em>m</em> vector.\n     *\n     * @param  A the <em>m</em>-by-<em>n</em> constraint matrix\n     * @param  b the length <em>m</em> right-hand-side vector\n     * @throws IllegalArgumentException if the dimensions disagree, i.e.,\n     *         the length of {@code b} does not equal {@code m}\n     */\n    public GaussianElimination(double[][] A, double[] b) {\n        m = A.length;\n        n = A[0].length;\n\n        if (b.length != m) throw new IllegalArgumentException(\"Dimensions disagree\");\n\n        // build augmented matrix\n        a = new double[m][n+1];\n        for (int i = 0; i < m; i++)\n            for (int j = 0; j < n; j++)\n                a[i][j] = A[i][j];\n        for (int i = 0; i < m; i++)\n            a[i][n] = b[i];\n\n        forwardElimination();\n\n        assert certifySolution(A, b);\n    }\n\n    // forward elimination\n    private void forwardElimination() {\n        for (int p = 0; p < Math.min(m, n); p++) {\n\n            // find pivot row using partial pivoting\n            int max = p;\n            for (int i = p+1; i < m; i++) {\n                if (Math.abs(a[i][p]) > Math.abs(a[max][p])) {\n                    max = i;\n                }\n            }\n\n            // swap\n            swap(p, max);\n\n            // singular or nearly singular\n            if (Math.abs(a[p][p]) <= EPSILON) {\n                continue;\n            }\n\n            // pivot\n            pivot(p);\n        }\n    }\n\n    // swap row1 and row2\n    private void swap(int row1, int row2) {\n        double[] temp = a[row1];\n        a[row1] = a[row2];\n        a[row2] = temp;\n    }\n\n    // pivot on a[p][p]\n    private void pivot(int p) {\n        for (int i = p+1; i < m; i++) {\n            double alpha = a[i][p] / a[p][p];\n            for (int j = p; j <= n; j++) {\n                a[i][j] -= alpha * a[p][j];\n            }\n        }\n    }\n\n    /**\n     * Returns a solution to the linear system of equations <em>Ax</em> = <em>b</em>.\n     *\n     * @return a solution <em>x</em> to the linear system of equations\n     *         <em>Ax</em> = <em>b</em>; {@code null} if no such solution\n     */\n    public double[] primal() {\n        // back substitution\n        double[] x = new double[n];\n        for (int i = Math.min(n-1, m-1); i >= 0; i--) {\n            double sum = 0.0;\n            for (int j = i+1; j < n; j++) {\n                sum += a[i][j] * x[j];\n            }\n\n            if (Math.abs(a[i][i]) > EPSILON)\n                x[i] = (a[i][n] - sum) / a[i][i];\n            else if (Math.abs(a[i][n] - sum) > EPSILON)\n                return null;\n        }\n\n        // redundant rows\n        for (int i = n; i < m; i++) {\n            double sum = 0.0;\n            for (int j = 0; j < n; j++) {\n                sum += a[i][j] * x[j];\n            }\n            if (Math.abs(a[i][n] - sum) > EPSILON)\n                return null;\n        }\n        return x;\n    }\n\n    /**\n     * Returns true if there exists a solution to the linear system of\n     * equations <em>Ax</em> = <em>b</em>.\n     *\n     * @return {@code true} if there exists a solution to the linear system\n     *         of equations <em>Ax</em> = <em>b</em>; {@code false} otherwise\n     */\n    public boolean isFeasible() {\n        return primal() != null;\n    }\n\n\n    // check that Ax = b\n    private boolean certifySolution(double[][] A, double[] b) {\n        if (!isFeasible()) return true;\n        double[] x = primal();\n        for (int i = 0; i < m; i++) {\n            double sum = 0.0;\n            for (int j = 0; j < n; j++) {\n                sum += A[i][j] * x[j];\n            }\n            if (Math.abs(sum - b[i]) > EPSILON) {\n                StdOut.println(\"not feasible\");\n                StdOut.println(\"b[\" + i + \"] = \" + b[i] + \", sum = \" + sum);\n                return false;\n            }\n        }\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code GaussianElimination} data type.\n     */\n    private static void test(String name, double[][] A, double[] b) {\n        StdOut.println(\"----------------------------------------------------\");\n        StdOut.println(name);\n        StdOut.println(\"----------------------------------------------------\");\n        GaussianElimination gaussian = new GaussianElimination(A, b);\n        double[] x = gaussian.primal();\n        if (gaussian.isFeasible()) {\n            for (int i = 0; i < x.length; i++) {\n                StdOut.printf(\"%.6f\\n\", x[i]);\n            }\n        }\n        else {\n            StdOut.println(\"System is infeasible\");\n        }\n        StdOut.println();\n        StdOut.println();\n    }\n\n\n    // 3-by-3 nonsingular system\n    private static void test1() {\n        double[][] A = {\n            { 0, 1,  1 },\n            { 2, 4, -2 },\n            { 0, 3, 15 }\n        };\n        double[] b = { 4, 2, 36 };\n        test(\"test 1 (3-by-3 system, nonsingular)\", A, b);\n    }\n\n    // 3-by-3 nonsingular system\n    private static void test2() {\n        double[][] A = {\n            {  1, -3,   1 },\n            {  2, -8,   8 },\n            { -6,  3, -15 }\n        };\n        double[] b = { 4, -2, 9 };\n        test(\"test 2 (3-by-3 system, nonsingular)\", A, b);\n    }\n\n    // 5-by-5 singular: no solutions\n    private static void test3() {\n        double[][] A = {\n            {  2, -3, -1,  2,  3 },\n            {  4, -4, -1,  4, 11 },\n            {  2, -5, -2,  2, -1 },\n            {  0,  2,  1,  0,  4 },\n            { -4,  6,  0,  0,  7 },\n        };\n        double[] b = { 4, 4, 9, -6, 5 };\n        test(\"test 3 (5-by-5 system, no solutions)\", A, b);\n    }\n\n    // 5-by-5 singular: infinitely many solutions\n    private static void test4() {\n        double[][] A = {\n            {  2, -3, -1,  2,  3 },\n            {  4, -4, -1,  4, 11 },\n            {  2, -5, -2,  2, -1 },\n            {  0,  2,  1,  0,  4 },\n            { -4,  6,  0,  0,  7 },\n        };\n        double[] b = { 4, 4, 9, -5, 5 };\n        test(\"test 4 (5-by-5 system, infinitely many solutions)\", A, b);\n    }\n\n    // 3-by-3 singular: no solutions\n    private static void test5() {\n        double[][] A = {\n            {  2, -1,  1 },\n            {  3,  2, -4 },\n            { -6,  3, -3 },\n        };\n        double[] b = { 1, 4, 2 };\n        test(\"test 5 (3-by-3 system, no solutions)\", A, b);\n    }\n\n    // 3-by-3 singular: infinitely many solutions\n    private static void test6() {\n        double[][] A = {\n            {  1, -1,  2 },\n            {  4,  4, -2 },\n            { -2,  2, -4 },\n        };\n        double[] b = { -3, 1, 6 };\n        test(\"test 6 (3-by-3 system, infinitely many solutions)\", A, b);\n    }\n\n    // 4-by-3 full rank and feasible system\n    private static void test7() {\n        double[][] A = {\n            { 0, 1,  1 },\n            { 2, 4, -2 },\n            { 0, 3, 15 },\n            { 2, 8, 14 }\n        };\n        double[] b = { 4, 2, 36, 42 };\n        test(\"test 7 (4-by-3 system, full rank)\", A, b);\n    }\n\n    // 4-by-3 full rank and infeasible system\n    private static void test8() {\n        double[][] A = {\n            { 0, 1,  1 },\n            { 2, 4, -2 },\n            { 0, 3, 15 },\n            { 2, 8, 14 }\n        };\n        double[] b = { 4, 2, 36, 40 };\n        test(\"test 8 (4-by-3 system, no solution)\", A, b);\n    }\n\n    // 3-by-4 full rank system\n    private static void test9() {\n        double[][] A = {\n            {  1, -3,   1,  1 },\n            {  2, -8,   8,  2 },\n            { -6,  3, -15,  3 }\n        };\n        double[] b = { 4, -2, 9 };\n        test(\"test 9 (3-by-4 system, full rank)\", A, b);\n    }\n\n    /**\n     * Unit tests the {@code GaussianElimination} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        test1();\n        test2();\n        test3();\n        test4();\n        test5();\n        test6();\n        test7();\n        test8();\n        test9();\n\n        // n-by-n random system\n        int n = Integer.parseInt(args[0]);\n        double[][] A = new double[n][n];\n        for (int i = 0; i < n; i++)\n            for (int j = 0; j < n; j++)\n                A[i][j] = StdRandom.uniformInt(1000);\n        double[] b = new double[n];\n        for (int i = 0; i < n; i++)\n            b[i] = StdRandom.uniformInt(1000);\n\n        test(n + \"-by-\" + n + \" (probably nonsingular)\", A, b);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Genome.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Genome.java\n *  Execution:    java Genome - < input.txt   (compress)\n *  Execution:    java Genome + < input.txt   (expand)\n *  Dependencies: BinaryIn.java BinaryOut.java\n *  Data files:   https://algs4.cs.princeton.edu/55compression/genomeTiny.txt\n *\n *  Compress or expand a genomic sequence using a 2-bit code.\n *\n *  % more genomeTiny.txt\n *  ATAGATGCATAGCGCATAGCTAGATGTGCTAGC\n *\n *  % java Genome - < genomeTiny.txt | java Genome +\n *  ATAGATGCATAGCGCATAGCTAGATGTGCTAGC\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Genome} class provides static methods for compressing\n *  and expanding a genomic sequence using a 2-bit code.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Genome {\n\n    // Do not instantiate.\n    private Genome() { }\n\n    /**\n     * Reads a sequence of 8-bit extended ASCII characters over the alphabet\n     * { A, C, T, G } from standard input; compresses them using two bits per\n     * character; and writes the results to standard output.\n     */\n    public static void compress() {\n        Alphabet DNA = Alphabet.DNA;\n        String s = BinaryStdIn.readString();\n        int n = s.length();\n        BinaryStdOut.write(n);\n\n        // Write two-bit code for char.\n        for (int i = 0; i < n; i++) {\n            int d = DNA.toIndex(s.charAt(i));\n            BinaryStdOut.write(d, 2);\n        }\n        BinaryStdOut.close();\n    }\n\n    /**\n     * Reads a binary sequence from standard input; converts each two bits\n     * to an 8-bit extended ASCII character over the alphabet { A, C, T, G };\n     * and writes the results to standard output.\n     */\n    public static void expand() {\n        Alphabet DNA = Alphabet.DNA;\n        int n = BinaryStdIn.readInt();\n        // Read two bits; write char.\n        for (int i = 0; i < n; i++) {\n            char c = BinaryStdIn.readChar(2);\n            BinaryStdOut.write(DNA.toChar(c), 8);\n        }\n        BinaryStdOut.close();\n    }\n\n\n    /**\n     * Sample client that calls {@code compress()} if the command-line\n     * argument is \"-\" an {@code expand()} if it is \"+\".\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        if      (args[0].equals(\"-\")) compress();\n        else if (args[0].equals(\"+\")) expand();\n        else throw new IllegalArgumentException(\"Illegal command line argument\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GlobalMincut.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GlobalMincut.java\n *  Execution:    java  GlobalMincut filename.txt\n *  Dependencies: EdgeWeightedGraph.java Edge.java UF.java\n *                IndexMaxPQ.java FlowNetwork.java FlowEdge.java\n *                FordFulkerson.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *\n *  Computes a minimum cut using Stoer-Wagner's algorithm.\n *\n *  % java GlobalMincut tinyEWG.txt\n *    Min cut: 5\n *    Min cut weight = 0.9500000000000001\n *\n *  % java GlobalMincut mediumEWG.txt\n *    Min cut: 25 60 63 96 199 237\n *    Min cut weight = 0.14021\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code GlobalMincut} class represents a data type for computing a\n *  <em>global minimum cut</em> in a graph with non-negative edge weights.\n *  A <em>cut</em> is a partition of the vertices into two nonempty subsets.\n *  An edge that has one\n *  endpoint in each subset of a cut is a <em>crossing edge</em>. The weight\n *  of a cut is the sum of the weights of its crossing edges.\n *  A <em>global minimum cut</em> whose weight is no larger than the weight\n *  of any other cut.\n *  <p>\n *  This is an implementation of <em>Stoer-Wagner's algorithm</em>.\n *  The constructor takes\n *  <em>O</em>(<em>V</em> (<em>V</em> + <em>E</em>) log <em>V</em>) time,\n *  where <em>V</em> is the number of vertices and <em>E</em> is the\n *  number of edges.\n *  The <em>weight</em> and <em>isCut</em> methods take &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  For additional documentation, see\n *  <ul>\n *  <li>M. Stoer and F. Wagner (1997). A simple min-cut algorithm. <em>Journal of\n *  the ACM </em>, 44(4):585-591.\n *  </ul>\n *\n * @author Marcelo Silva\n */\npublic class GlobalMincut {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-11;\n\n    // the weight of the minimum cut\n    private double weight = Double.POSITIVE_INFINITY;\n\n    // cut[v] = true if v is on the first subset of vertices of the minimum cut;\n    // or false if v is on the second subset\n    private boolean[] cut;\n\n    // number of vertices\n    private int V;\n\n    /**\n     * This helper class represents the <em>cut-of-the-phase</em>. The\n     * cut-of-the-phase is a <em>minimum s-t-cut</em> in the current graph,\n     * where {@code s} and {@code t} are the two vertices added last in the\n     * phase.\n     */\n    private class CutPhase {\n        private double weight; // the weight of the minimum s-t cut\n        private int s;         // the vertex s\n        private int t;         // the vertex t\n\n        public CutPhase(double weight, int s, int t) {\n            this.weight = weight;\n            this.s = s;\n            this.t = t;\n        }\n    }\n\n    /**\n     * Computes a minimum cut in an edge-weighted graph.\n     *\n     * @param G the edge-weighted graph\n     * @throws IllegalArgumentException if the number of vertices of {@code G}\n     *             is less than {@code 2}.\n     * @throws IllegalArgumentException if any edge weight is negative\n     */\n    public GlobalMincut(EdgeWeightedGraph G) {\n        V = G.V();\n        validate(G);\n        minCut(G, 0);\n        assert check(G);\n    }\n\n    /**\n     * Validates the edge-weighted graph.\n     *\n     * @param G the edge-weighted graph\n     * @throws IllegalArgumentException if the number of vertices of {@code G}\n     *             is less than {@code 2} or if any edge weight is negative\n     */\n    private void validate(EdgeWeightedGraph G) {\n        if (G.V() < 2) throw new IllegalArgumentException(\"number of vertices of G is less than 2\");\n        for (Edge e : G.edges()) {\n            if (e.weight() < 0) throw new IllegalArgumentException(\"edge \" + e + \" has negative weight\");\n        }\n    }\n\n    /**\n     * Returns the weight of the minimum cut.\n     *\n     * @return the weight of the minimum cut\n     */\n    public double weight() {\n        return weight;\n    }\n\n    /**\n     * Returns {@code true} if the vertex {@code v} is one side of the\n     * mincut and {@code false} otherwise. An edge <em>v</em>-<em>w</em>\n     * crosses the mincut if and only if <em>v</em> and <em>w</em> have\n     * opposite parity.\n     *\n     * @param v the vertex to check\n     * @return {@code true} if the vertex {@code v} is on the first subset of\n     *         vertices of the minimum cut; or {@code false} if the vertex\n     *         {@code v} is on the second subset.\n     * @throws IllegalArgumentException unless vertex {@code v} is between\n     *             {@code 0 <= v < V}\n     */\n    public boolean cut(int v) {\n        validateVertex(v);\n        return cut[v];\n    }\n\n    /**\n     * Makes a cut for the current edge-weighted graph by partitioning its\n     * vertices into two nonempty subsets. The vertices connected to the\n     * vertex {@code t} belong to the first subset. Other vertices not connected\n     * to {@code t} belong to the second subset.\n     *\n     * @param t the vertex {@code t}\n     * @param uf the union-find data type\n     */\n    private void makeCut(int t, UF uf) {\n        for (int v = 0; v < cut.length; v++) {\n            cut[v] = (uf.find(v) == uf.find(t));\n        }\n    }\n\n    /**\n     * Computes a minimum cut of the edge-weighted graph. Precisely, it computes\n     * the lightest of the cuts-of-the-phase which yields the desired minimum\n     * cut.\n     *\n     * @param G the edge-weighted graph\n     * @param a the starting vertex\n     */\n    private void minCut(EdgeWeightedGraph G, int a) {\n        UF uf = new UF(G.V());\n        boolean[] marked = new boolean[G.V()];\n        cut = new boolean[G.V()];\n        CutPhase cp = new CutPhase(0.0, a, a);\n        for (int v = G.V(); v > 1; v--) {\n            minCutPhase(G, marked, cp);\n            if (cp.weight < weight) {\n                weight = cp.weight;\n                makeCut(cp.t, uf);\n            }\n            G = contractEdge(G, cp.s, cp.t);\n            marked[cp.t] = true;\n            uf.union(cp.s, cp.t);\n        }\n    }\n\n    /**\n     * Returns the cut-of-the-phase. The cut-of-the-phase is a minimum s-t-cut\n     * in the current graph, where {@code s} and {@code t} are the two vertices\n     * added last in the phase. This algorithm is known in the literature as\n     * <em>maximum adjacency search</em> or <em>maximum cardinality search</em>.\n     *\n     * @param G the edge-weighted graph\n     * @param marked the array of contracted vertices, where {@code marked[v]}\n     *            is {@code true} if the vertex {@code v} was already\n     *            contracted; or {@code false} otherwise\n     * @param cp the previous cut-of-the-phase\n     * @return the cut-of-the-phase\n     */\n    private void minCutPhase(EdgeWeightedGraph G, boolean[] marked, CutPhase cp) {\n        IndexMaxPQ<Double> pq = new IndexMaxPQ<Double>(G.V());\n        for (int v = 0; v < G.V(); v++) {\n            if (v != cp.s && !marked[v]) pq.insert(v, 0.0);\n        }\n        pq.insert(cp.s, Double.POSITIVE_INFINITY);\n        while (!pq.isEmpty()) {\n            int v = pq.delMax();\n            cp.s = cp.t;\n            cp.t = v;\n            for (Edge e : G.adj(v)) {\n                int w = e.other(v);\n                if (pq.contains(w)) pq.increaseKey(w, pq.keyOf(w) + e.weight());\n            }\n        }\n        cp.weight = 0.0;\n        for (Edge e : G.adj(cp.t)) {\n            cp.weight += e.weight();\n        }\n    }\n\n    /**\n     * Contracts the edges incidents on the vertices {@code s} and {@code t} of\n     * the given edge-weighted graph.\n     *\n     * @param G the edge-weighted graph\n     * @param s the vertex {@code s}\n     * @param t the vertex {@code t}\n     * @return a new edge-weighted graph for which the edges incidents on the\n     *         vertices {@code s} and {@code t} were contracted\n     */\n    private EdgeWeightedGraph contractEdge(EdgeWeightedGraph G, int s, int t) {\n        EdgeWeightedGraph H = new EdgeWeightedGraph(G.V());\n        for (int v = 0; v < G.V(); v++) {\n            for (Edge e : G.adj(v)) {\n                int w = e.other(v);\n                if (v == s && w == t || v == t && w == s) continue;\n                if (v < w) {\n                    if (w == t)      H.addEdge(new Edge(v, s, e.weight()));\n                    else if (v == t) H.addEdge(new Edge(w, s, e.weight()));\n                    else             H.addEdge(new Edge(v, w, e.weight()));\n                }\n            }\n        }\n        return H;\n    }\n\n    /**\n     * Checks optimality conditions.\n     *\n     * @param G the edge-weighted graph\n     * @return {@code true} if optimality conditions are fine\n     */\n    private boolean check(EdgeWeightedGraph G) {\n\n        // compute min st-cut for all pairs s and t\n        // shortcut: s must appear on one side of global mincut,\n        // so it suffices to try all pairs s-v for some fixed s\n        double value = Double.POSITIVE_INFINITY;\n        for (int s = 0, t = 1; t < G.V(); t++) {\n            FlowNetwork F = new FlowNetwork(G.V());\n            for (Edge e : G.edges()) {\n                int v = e.either(), w = e.other(v);\n                F.addEdge(new FlowEdge(v, w, e.weight()));\n                F.addEdge(new FlowEdge(w, v, e.weight()));\n            }\n            FordFulkerson maxflow = new FordFulkerson(F, s, t);\n            value = Math.min(value, maxflow.value());\n        }\n        if (Math.abs(weight - value) > FLOATING_POINT_EPSILON) {\n            System.err.println(\"Min cut weight = \" + weight + \" , max flow value = \" + value);\n            return false;\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n\n    /**\n     * Unit tests the {@code GlobalMincut} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph G = new EdgeWeightedGraph(in);\n        GlobalMincut mc = new GlobalMincut(G);\n        StdOut.print(\"Min cut: \");\n        for (int v = 0; v < G.V(); v++) {\n            if (mc.cut(v)) StdOut.print(v + \" \");\n        }\n        StdOut.println();\n        StdOut.println(\"Min cut weight = \" + mc.weight());\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GrahamScan.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GrahamScan.java\n *  Execution:    java GrahamScan < input.txt\n *  Dependencies: Point2D.java\n *  Data files:   https://algs4.cs.princeton.edu/99hull/rs1423.txt\n *                https://algs4.cs.princeton.edu/99hull/kw1260.txt\n *\n *  Create points from standard input and compute the convex hull using\n *  Graham scan algorithm.\n *\n *  May be floating-point issues if x- and y-coordinates are not integers.\n *\n *  % java GrahamScan < input100.txt\n *  (7486.0, 422.0)\n *  (29413.0, 596.0)\n *  (32011.0, 3140.0)\n *  (30875.0, 28560.0)\n *  (28462.0, 32343.0)\n *  (15731.0, 32661.0)\n *  (822.0, 32301.0)\n *  (823.0, 15895.0)\n *  (1444.0, 10362.0)\n *  (4718.0, 4451.0)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n\n/**\n *  The {@code GrahamScan} data type provides methods for computing the \n *  convex hull of a set of <em>n</em> points in the plane.\n *  <p>\n *  The implementation uses the Graham-Scan convex hull algorithm.\n *  It runs in O(<em>n</em> log <em>n</em>) time in the worst case\n *  and uses O(<em>n</em>) extra memory.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/99scientific\">Section 9.9</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class GrahamScan {\n    private Stack<Point2D> hull = new Stack<Point2D>();\n\n    /**\n     * Computes the convex hull of the specified array of points.\n     *\n     * @param  points the array of points\n     * @throws IllegalArgumentException if {@code points} is {@code null}\n     * @throws IllegalArgumentException if any entry in {@code points[]} is {@code null}\n     * @throws IllegalArgumentException if {@code points.length} is {@code 0}\n     */\n    public GrahamScan(Point2D[] points) {\n        if (points == null) throw new IllegalArgumentException(\"argument is null\");\n        if (points.length == 0) throw new IllegalArgumentException(\"array is of length 0\");\n\n        // defensive copy\n        int n = points.length;\n        Point2D[] a = new Point2D[n];\n        for (int i = 0; i < n; i++) {\n            if (points[i] == null)\n                throw new IllegalArgumentException(\"points[\" + i + \"] is null\");\n            a[i] = points[i];\n        }\n\n        // preprocess so that a[0] has lowest y-coordinate; break ties by x-coordinate\n        // a[0] is an extreme point of the convex hull\n        // (alternatively, could do easily in linear time)\n        Arrays.sort(a);\n\n        // sort by polar angle with respect to base point a[0],\n        // breaking ties by distance to a[0]\n        Arrays.sort(a, 1, n, a[0].polarOrder());\n\n        hull.push(a[0]);       // a[0] is first extreme point\n\n        // find index k1 of first point not equal to a[0]\n        int k1;\n        for (k1 = 1; k1 < n; k1++)\n            if (!a[0].equals(a[k1])) break;\n        if (k1 == n) return;        // all points equal\n\n        // find index k2 of first point not collinear with a[0] and a[k1]\n        int k2;\n        for (k2 = k1+1; k2 < n; k2++)\n            if (Point2D.ccw(a[0], a[k1], a[k2]) != 0) break;\n        hull.push(a[k2-1]);    // a[k2-1] is second extreme point\n\n        // Graham scan; note that a[n-1] is extreme point different from a[0]\n        for (int i = k2; i < n; i++) {\n            Point2D top = hull.pop();\n            while (Point2D.ccw(hull.peek(), top, a[i]) <= 0) {\n                top = hull.pop();\n            }\n            hull.push(top);\n            hull.push(a[i]);\n        }\n\n        assert isConvex();\n    }\n\n    /**\n     * Returns the extreme points on the convex hull in counterclockwise order.\n     *\n     * @return the extreme points on the convex hull in counterclockwise order\n     */\n    public Iterable<Point2D> hull() {\n        Stack<Point2D> s = new Stack<Point2D>();\n        for (Point2D p : hull) s.push(p);\n        return s;\n    }\n\n    // check that boundary of hull is strictly convex\n    private boolean isConvex() {\n        int n = hull.size();\n        if (n <= 2) return true;\n\n        Point2D[] points = new Point2D[n];\n        int k = 0;\n        for (Point2D p : hull()) {\n            points[k++] = p;\n        }\n\n        for (int i = 0; i < n; i++) {\n            if (Point2D.ccw(points[i], points[(i+1) % n], points[(i+2) % n]) <= 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n   /**\n     * Unit tests the {@code GrahamScan} data type.\n     * Reads in an integer {@code n} and {@code n} points (specified by\n     * their <em>x</em>- and <em>y</em>-coordinates) from standard input;\n     * computes their convex hull; and prints out the points on the\n     * convex hull to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        Point2D[] points = new Point2D[n];\n        for (int i = 0; i < n; i++) {\n            int x = StdIn.readInt();\n            int y = StdIn.readInt();\n            points[i] = new Point2D(x, y);\n        }\n        GrahamScan graham = new GrahamScan(points);\n        for (Point2D p : graham.hull())\n            StdOut.println(p);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Graph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Graph.java\n *  Execution:    java Graph input.txt\n *  Dependencies: Bag.java Stack.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *                https://algs4.cs.princeton.edu/41graph/largeG.txt\n *\n *  A graph, implemented using an array of sets.\n *  Parallel edges and self-loops allowed.\n *\n *  % java Graph tinyG.txt\n *  13 vertices, 13 edges\n *  0: 6 2 1 5\n *  1: 0\n *  2: 0\n *  3: 5 4\n *  4: 5 6 3\n *  5: 3 4 0\n *  6: 0 4\n *  7: 8\n *  8: 7\n *  9: 11 10 12\n *  10: 9\n *  11: 9 12\n *  12: 11 9\n *\n *  % java Graph mediumG.txt\n *  250 vertices, 1273 edges\n *  0: 225 222 211 209 204 202 191 176 163 160 149 114 97 80 68 59 58 49 44 24 15\n *  1: 220 203 200 194 189 164 150 130 107 72\n *  2: 141 110 108 86 79 51 42 18 14\n *  ...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code Graph} class represents an undirected graph of vertices\n *  named 0 through <em>V</em> – 1.\n *  It supports the following two primary operations: add an edge to the graph,\n *  iterate over all of the vertices adjacent with a given vertex. It also provides\n *  methods for returning the degree of a vertex, the number of vertices\n *  <em>V</em> in the graph, and the number of edges <em>E</em> in the graph.\n *  Parallel edges and self-loops are permitted.\n *  By convention, a self-loop <em>v</em>-<em>v</em> appears in the\n *  adjacency list of <em>v</em> twice and contributes two to the degree\n *  of <em>v</em>.\n *  <p>\n *  This implementation uses an <em>adjacency-lists representation</em>, which\n *  is a vertex-indexed array of {@link Bag} objects.\n *  It uses &Theta;(<em>E</em> + <em>V</em>) space, where <em>E</em> is\n *  the number of edges and <em>V</em> is the number of vertices.\n *  All instance methods take &Theta;(1) time. (Though, iterating over\n *  the vertices returned by {@link #adj(int)} takes time proportional\n *  to the degree of the vertex.)\n *  Constructing an empty graph with <em>V</em> vertices takes\n *  &Theta;(<em>V</em>) time; constructing a graph with <em>E</em> edges\n *  and <em>V</em> vertices takes &Theta;(<em>E</em> + <em>V</em>) time.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Graph {\n    private static final String NEWLINE = System.getProperty(\"line.separator\");\n\n    private final int V;\n    private int E;\n    private Bag<Integer>[] adj;\n\n    /**\n     * Initializes an empty graph with {@code V} vertices and 0 edges.\n     * param V the number of vertices\n     *\n     * @param  V number of vertices\n     * @throws IllegalArgumentException if {@code V < 0}\n     */\n    public Graph(int V) {\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices must be non-negative\");\n        this.V = V;\n        this.E = 0;\n        adj = (Bag<Integer>[]) new Bag[V];\n        for (int v = 0; v < V; v++) {\n            adj[v] = new Bag<Integer>();\n        }\n    }\n\n    /**\n     * Initializes a graph from the specified input stream.\n     * The format is the number of vertices <em>V</em>,\n     * followed by the number of edges <em>E</em>,\n     * followed by <em>E</em> pairs of vertices, with each entry separated by whitespace.\n     *\n     * @param  in the input stream\n     * @throws IllegalArgumentException if {@code in} is {@code null}\n     * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range\n     * @throws IllegalArgumentException if the number of vertices or edges is negative\n     * @throws IllegalArgumentException if the input stream is in the wrong format\n     */\n    public Graph(In in) {\n        if (in == null) throw new IllegalArgumentException(\"argument is null\");\n        try {\n            this.V = in.readInt();\n            if (V < 0) throw new IllegalArgumentException(\"number of vertices in a Graph must be non-negative\");\n            adj = (Bag<Integer>[]) new Bag[V];\n            for (int v = 0; v < V; v++) {\n                adj[v] = new Bag<Integer>();\n            }\n            int E = in.readInt();\n            if (E < 0) throw new IllegalArgumentException(\"number of edges in a Graph must be non-negative\");\n            for (int i = 0; i < E; i++) {\n                int v = in.readInt();\n                int w = in.readInt();\n                validateVertex(v);\n                validateVertex(w);\n                addEdge(v, w);\n            }\n        }\n        catch (NoSuchElementException e) {\n            throw new IllegalArgumentException(\"invalid input format in Graph constructor\", e);\n        }\n    }\n\n\n    /**\n     * Initializes a new graph that is a deep copy of {@code graph}.\n     *\n     * @param  graph the graph to copy\n     * @throws IllegalArgumentException if {@code graph} is {@code null}\n     */\n    public Graph(Graph graph) {\n        this.V = graph.V();\n        this.E = graph.E();\n        if (V < 0) throw new IllegalArgumentException(\"Number of vertices must be non-negative\");\n\n        // update adjacency lists\n        adj = (Bag<Integer>[]) new Bag[V];\n        for (int v = 0; v < V; v++) {\n            adj[v] = new Bag<Integer>();\n        }\n\n        for (int v = 0; v < graph.V(); v++) {\n            // reverse so that adjacency list is in same order as original\n            Stack<Integer> reverse = new Stack<Integer>();\n            for (int w : graph.adj[v]) {\n                reverse.push(w);\n            }\n            for (int w : reverse) {\n                adj[v].add(w);\n            }\n        }\n    }\n\n    /**\n     * Returns the number of vertices in this graph.\n     *\n     * @return the number of vertices in this graph\n     */\n    public int V() {\n        return V;\n    }\n\n    /**\n     * Returns the number of edges in this graph.\n     *\n     * @return the number of edges in this graph\n     */\n    public int E() {\n        return E;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Adds the undirected edge v-w to this graph.\n     *\n     * @param  v one vertex in the edge\n     * @param  w the other vertex in the edge\n     * @throws IllegalArgumentException unless both {@code 0 <= v < V} and {@code 0 <= w < V}\n     */\n    public void addEdge(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        E++;\n        adj[v].add(w);\n        adj[w].add(v);\n    }\n\n\n    /**\n     * Returns the vertices adjacent with vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the vertices adjacent with vertex {@code v}, as an iterable\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public Iterable<Integer> adj(int v) {\n        validateVertex(v);\n        return adj[v];\n    }\n\n    /**\n     * Returns the degree of vertex {@code v}.\n     *\n     * @param  v the vertex\n     * @return the degree of vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int degree(int v) {\n        validateVertex(v);\n        return adj[v].size();\n    }\n\n\n    /**\n     * Returns a string representation of this graph.\n     *\n     * @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>,\n     *         followed by the <em>V</em> adjacency lists\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(V + \" vertices, \" + E + \" edges \" + NEWLINE);\n        for (int v = 0; v < V; v++) {\n            s.append(v + \": \");\n            for (int w : adj[v]) {\n                s.append(w + \" \");\n            }\n            s.append(NEWLINE);\n        }\n        return s.toString();\n    }\n\n    /**\n     * Returns a string representation of this graph in DOT format,\n     * suitable for visualization with Graphviz.\n     *\n     * To visualize the graph, install Graphviz (e.g., \"brew install graphviz\").\n     * Then use one of the graph visualization tools\n     *    - dot    (hierarchical or layer drawing)\n     *    - neato  (spring model)\n     *    - fdp    (force-directed placement)\n     *    - sfdp   (scalable force-directed placement)\n     *    - twopi  (radial layout)\n     *\n     * For example, the following commands will create graph drawings in SVG\n     * and PDF formats\n     *    - dot input.dot -Tsvg -o output.svg\n     *    - dot input.dot -Tpdf -o output.pdf\n     *\n     * To change the graph attributes (e.g., vertex and edge shapes, arrows, colors)\n     *  in the DOT format, see https://graphviz.org/doc/info/lang.html\n     *\n     * @return a string representation of this graph in DOT format\n     */\n    public String toDot() {\n        StringBuilder s = new StringBuilder();\n        s.append(\"graph {\" + NEWLINE);\n        s.append(\"node[shape=circle, style=filled, fixedsize=true, width=0.3, fontsize=\\\"10pt\\\"]\" + NEWLINE);\n        int selfLoops = 0;\n        for (int v = 0; v < V; v++) {\n            for (int w : adj[v]) {\n                if (v < w) {\n                    s.append(v + \" -- \" + w + NEWLINE);\n                }\n                else if (v == w) {\n                    // include only one copy of each self loop (self loops will be consecutive)\n                    if (selfLoops % 2 == 0) {\n                        s.append(v + \" -- \" + w + NEWLINE);\n                    }\n                    selfLoops++;\n                }\n            }\n        }\n        s.append(\"}\" + NEWLINE);\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code Graph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        StdOut.println(graph);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GraphGenerator.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GraphGenerator.java\n *  Execution:    java GraphGenerator V E\n *  Dependencies: Graph.java\n *\n *  A graph generator.\n *\n *  For many more graph generators, see\n *  http://networkx.github.io/documentation/latest/reference/generators.html\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code GraphGenerator} class provides static methods for creating\n *  various graphs, including Erdos-Renyi random graphs, random bipartite\n *  graphs, random k-regular graphs, and random rooted trees.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class GraphGenerator {\n    private static final class Edge implements Comparable<Edge> {\n        private int v;\n        private int w;\n\n        private Edge(int v, int w) {\n            if (v < w) {\n                this.v = v;\n                this.w = w;\n            }\n            else {\n                this.v = w;\n                this.w = v;\n            }\n        }\n\n        public int compareTo(Edge that) {\n            if (this.v < that.v) return -1;\n            if (this.v > that.v) return +1;\n            if (this.w < that.w) return -1;\n            if (this.w > that.w) return +1;\n            return 0;\n        }\n    }\n\n    // this class cannot be instantiated\n    private GraphGenerator() { }\n\n    /**\n     * Returns a random simple graph containing {@code V} vertices and {@code E} edges.\n     * @param V the number of vertices\n     * @param E the number of vertices\n     * @return a random simple graph on {@code V} vertices, containing a total\n     *     of {@code E} edges\n     * @throws IllegalArgumentException if no such simple graph exists\n     */\n    public static Graph simple(int V, int E) {\n        if (E > (long) V*(V-1)/2) throw new IllegalArgumentException(\"Too many edges\");\n        if (E < 0)                throw new IllegalArgumentException(\"Too few edges\");\n        Graph graph = new Graph(V);\n        SET<Edge> set = new SET<Edge>();\n        while (graph.E() < E) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            Edge e = new Edge(v, w);\n            if ((v != w) && !set.contains(e)) {\n                set.add(e);\n                graph.addEdge(v, w);\n            }\n        }\n        return graph;\n    }\n\n    /**\n     * Returns a random simple graph on {@code V} vertices, with an\n     * edge between any two vertices with probability {@code p}. This is sometimes\n     * referred to as the Erdos-Renyi random graph model.\n     * @param V the number of vertices\n     * @param p the probability of choosing an edge\n     * @return a random simple graph on {@code V} vertices, with an edge between\n     *     any two vertices with probability {@code p}\n     * @throws IllegalArgumentException if probability is not between 0 and 1\n     */\n    public static Graph simple(int V, double p) {\n        if (p < 0.0 || p > 1.0)\n            throw new IllegalArgumentException(\"Probability must be between 0 and 1\");\n        Graph graph = new Graph(V);\n        for (int v = 0; v < V; v++)\n            for (int w = v+1; w < V; w++)\n                if (StdRandom.bernoulli(p))\n                    graph.addEdge(v, w);\n        return graph;\n    }\n\n    /**\n     * Returns the complete graph on {@code V} vertices.\n     * @param V the number of vertices\n     * @return the complete graph on {@code V} vertices\n     */\n    public static Graph complete(int V) {\n        return simple(V, 1.0);\n    }\n\n    /**\n     * Returns a complete bipartite graph on {@code V1} and {@code V2} vertices.\n     * @param V1 the number of vertices in one partition\n     * @param V2 the number of vertices in the other partition\n     * @return a complete bipartite graph on {@code V1} and {@code V2} vertices\n     * @throws IllegalArgumentException if probability is not between 0 and 1\n     */\n    public static Graph completeBipartite(int V1, int V2) {\n        return bipartite(V1, V2, V1*V2);\n    }\n\n    /**\n     * Returns a random simple bipartite graph on {@code V1} and {@code V2} vertices\n     * with {@code E} edges.\n     * @param V1 the number of vertices in one partition\n     * @param V2 the number of vertices in the other partition\n     * @param E the number of edges\n     * @return a random simple bipartite graph on {@code V1} and {@code V2} vertices,\n     *    containing a total of {@code E} edges\n     * @throws IllegalArgumentException if no such simple bipartite graph exists\n     */\n    public static Graph bipartite(int V1, int V2, int E) {\n        if (E > (long) V1*V2) throw new IllegalArgumentException(\"Too many edges\");\n        if (E < 0)            throw new IllegalArgumentException(\"Too few edges\");\n        Graph graph = new Graph(V1 + V2);\n\n        int[] vertices = new int[V1 + V2];\n        for (int i = 0; i < V1 + V2; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n\n        SET<Edge> set = new SET<Edge>();\n        while (graph.E() < E) {\n            int i = StdRandom.uniformInt(V1);\n            int j = V1 + StdRandom.uniformInt(V2);\n            Edge e = new Edge(vertices[i], vertices[j]);\n            if (!set.contains(e)) {\n                set.add(e);\n                graph.addEdge(vertices[i], vertices[j]);\n            }\n        }\n        return graph;\n    }\n\n    /**\n     * Returns a random simple bipartite graph on {@code V1} and {@code V2} vertices,\n     * containing each possible edge with probability {@code p}.\n     * @param V1 the number of vertices in one partition\n     * @param V2 the number of vertices in the other partition\n     * @param p the probability that the graph contains an edge with one endpoint in either side\n     * @return a random simple bipartite graph on {@code V1} and {@code V2} vertices,\n     *    containing each possible edge with probability {@code p}\n     * @throws IllegalArgumentException if probability is not between 0 and 1\n     */\n    public static Graph bipartite(int V1, int V2, double p) {\n        if (p < 0.0 || p > 1.0)\n            throw new IllegalArgumentException(\"Probability must be between 0 and 1\");\n        int[] vertices = new int[V1 + V2];\n        for (int i = 0; i < V1 + V2; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        Graph graph = new Graph(V1 + V2);\n        for (int i = 0; i < V1; i++)\n            for (int j = 0; j < V2; j++)\n                if (StdRandom.bernoulli(p))\n                    graph.addEdge(vertices[i], vertices[V1+j]);\n        return graph;\n    }\n\n    /**\n     * Returns a path graph on {@code V} vertices.\n     * @param V the number of vertices in the path\n     * @return a path graph on {@code V} vertices\n     */\n    public static Graph path(int V) {\n        Graph graph = new Graph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V-1; i++) {\n            graph.addEdge(vertices[i], vertices[i+1]);\n        }\n        return graph;\n    }\n\n    /**\n     * Returns a complete binary tree graph on {@code V} vertices.\n     * @param V the number of vertices in the binary tree\n     * @return a complete binary tree graph on {@code V} vertices\n     */\n    public static Graph binaryTree(int V) {\n        Graph graph = new Graph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 1; i < V; i++) {\n            graph.addEdge(vertices[i], vertices[(i-1)/2]);\n        }\n        return graph;\n    }\n\n    /**\n     * Returns a cycle graph on {@code V} vertices.\n     * @param V the number of vertices in the cycle\n     * @return a cycle graph on {@code V} vertices\n     */\n    public static Graph cycle(int V) {\n        Graph graph = new Graph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V-1; i++) {\n            graph.addEdge(vertices[i], vertices[i+1]);\n        }\n        graph.addEdge(vertices[V-1], vertices[0]);\n        return graph;\n    }\n\n    /**\n     * Returns an Eulerian cycle graph on {@code V} vertices.\n     *\n     * @param  V the number of vertices in the cycle\n     * @param  E the number of edges in the cycle\n     * @return a graph that is an Eulerian cycle on {@code V} vertices\n     *         and {@code E} edges\n     * @throws IllegalArgumentException if either {@code V <= 0} or {@code E <= 0}\n     */\n    public static Graph eulerianCycle(int V, int E) {\n        if (E <= 0)\n            throw new IllegalArgumentException(\"An Eulerian cycle must have at least one edge\");\n        if (V <= 0)\n            throw new IllegalArgumentException(\"An Eulerian cycle must have at least one vertex\");\n        Graph graph = new Graph(V);\n        int[] vertices = new int[E];\n        for (int i = 0; i < E; i++)\n            vertices[i] = StdRandom.uniformInt(V);\n        for (int i = 0; i < E-1; i++) {\n            graph.addEdge(vertices[i], vertices[i+1]);\n        }\n        graph.addEdge(vertices[E-1], vertices[0]);\n        return graph;\n    }\n\n    /**\n     * Returns an Eulerian path graph on {@code V} vertices.\n     *\n     * @param  V the number of vertices in the path\n     * @param  E the number of edges in the path\n     * @return a graph that is an Eulerian path on {@code V} vertices\n     *         and {@code E} edges\n     * @throws IllegalArgumentException if either {@code V <= 0} or {@code E < 0}\n     */\n    public static Graph eulerianPath(int V, int E) {\n        if (E < 0)\n            throw new IllegalArgumentException(\"negative number of edges\");\n        if (V <= 0)\n            throw new IllegalArgumentException(\"An Eulerian path must have at least one vertex\");\n        Graph graph = new Graph(V);\n        int[] vertices = new int[E+1];\n        for (int i = 0; i < E+1; i++)\n            vertices[i] = StdRandom.uniformInt(V);\n        for (int i = 0; i < E; i++) {\n            graph.addEdge(vertices[i], vertices[i+1]);\n        }\n        return graph;\n    }\n\n    /**\n     * Returns a wheel graph on {@code V} vertices.\n     * @param V the number of vertices in the wheel\n     * @return a wheel graph on {@code V} vertices: a single vertex connected to\n     *     every vertex in a cycle on {@code V-1} vertices\n     */\n    public static Graph wheel(int V) {\n        if (V <= 1) throw new IllegalArgumentException(\"Number of vertices must be at least 2\");\n        Graph graph = new Graph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n\n        // simple cycle on V-1 vertices\n        for (int i = 1; i < V-1; i++) {\n            graph.addEdge(vertices[i], vertices[i+1]);\n        }\n        graph.addEdge(vertices[V-1], vertices[1]);\n\n        // connect vertices[0] to every vertex on cycle\n        for (int i = 1; i < V; i++) {\n            graph.addEdge(vertices[0], vertices[i]);\n        }\n\n        return graph;\n    }\n\n    /**\n     * Returns a star graph on {@code V} vertices.\n     * @param V the number of vertices in the star\n     * @return a star graph on {@code V} vertices: a single vertex connected to\n     *     every other vertex\n     */\n    public static Graph star(int V) {\n        if (V <= 0) throw new IllegalArgumentException(\"Number of vertices must be at least 1\");\n        Graph graph = new Graph(V);\n        int[] vertices = new int[V];\n        for (int i = 0; i < V; i++)\n            vertices[i] = i;\n        StdRandom.shuffle(vertices);\n\n        // connect vertices[0] to every other vertex\n        for (int i = 1; i < V; i++) {\n            graph.addEdge(vertices[0], vertices[i]);\n        }\n\n        return graph;\n    }\n\n    /**\n     * Returns a uniformly random {@code k}-regular graph on {@code V} vertices\n     * (not necessarily simple). The graph is simple with probability only about e^(-k^2/4),\n     * which is tiny when k = 14.\n     *\n     * @param V the number of vertices in the graph\n     * @param k degree of each vertex\n     * @return a uniformly random {@code k}-regular graph on {@code V} vertices.\n     */\n    public static Graph regular(int V, int k) {\n        if (V*k % 2 != 0) throw new IllegalArgumentException(\"Number of vertices * k must be even\");\n        Graph graph = new Graph(V);\n\n        // create k copies of each vertex\n        int[] vertices = new int[V*k];\n        for (int v = 0; v < V; v++) {\n            for (int j = 0; j < k; j++) {\n                vertices[v + V*j] = v;\n            }\n        }\n\n        // pick a random perfect matching\n        StdRandom.shuffle(vertices);\n        for (int i = 0; i < V*k/2; i++) {\n            graph.addEdge(vertices[2*i], vertices[2*i + 1]);\n        }\n        return graph;\n    }\n\n    // http://www.proofwiki.org/wiki/Labeled_Tree_from_Prüfer_Sequence\n    // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.36.6484&rep=rep1&type=pdf\n    /**\n     * Returns a uniformly random tree on {@code V} vertices.\n     * This algorithm uses a Prufer sequence and takes time proportional to <em>V log V</em>.\n     * @param V the number of vertices in the tree\n     * @return a uniformly random tree on {@code V} vertices\n     */\n    public static Graph tree(int V) {\n        Graph graph = new Graph(V);\n\n        // special case\n        if (V == 1) return graph;\n\n        // Cayley's theorem: there are V^(V-2) labeled trees on V vertices\n        // Prufer sequence: sequence of V-2 values between 0 and V-1\n        // Prufer's proof of Cayley's theorem: Prufer sequences are in 1-1\n        // with labeled trees on V vertices\n        int[] prufer = new int[V-2];\n        for (int i = 0; i < V-2; i++)\n            prufer[i] = StdRandom.uniformInt(V);\n\n        // degree of vertex v = 1 + number of times it appears in Prufer sequence\n        int[] degree = new int[V];\n        for (int v = 0; v < V; v++)\n            degree[v] = 1;\n        for (int i = 0; i < V-2; i++)\n            degree[prufer[i]]++;\n\n        // pq contains all vertices of degree 1\n        MinPQ<Integer> pq = new MinPQ<Integer>();\n        for (int v = 0; v < V; v++)\n            if (degree[v] == 1) pq.insert(v);\n\n        // repeatedly delMin() degree 1 vertex that has the minimum index\n        for (int i = 0; i < V-2; i++) {\n            int v = pq.delMin();\n            graph.addEdge(v, prufer[i]);\n            degree[v]--;\n            degree[prufer[i]]--;\n            if (degree[prufer[i]] == 1) pq.insert(prufer[i]);\n        }\n        graph.addEdge(pq.delMin(), pq.delMin());\n        return graph;\n    }\n\n    /**\n     * Unit tests the {@code GraphGenerator} library.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        int V1 = V/2;\n        int V2 = V - V1;\n\n        StdOut.println(\"complete graph\");\n        StdOut.println(complete(V));\n        StdOut.println();\n\n        StdOut.println(\"simple\");\n        StdOut.println(simple(V, E));\n        StdOut.println();\n\n        StdOut.println(\"Erdos-Renyi\");\n        double p = (double) E / (V*(V-1)/2.0);\n        StdOut.println(simple(V, p));\n        StdOut.println();\n\n        StdOut.println(\"complete bipartite\");\n        StdOut.println(completeBipartite(V1, V2));\n        StdOut.println();\n\n        StdOut.println(\"bipartite\");\n        StdOut.println(bipartite(V1, V2, E));\n        StdOut.println();\n\n        StdOut.println(\"Erdos Renyi bipartite\");\n        double q = (double) E / (V1*V2);\n        StdOut.println(bipartite(V1, V2, q));\n        StdOut.println();\n\n        StdOut.println(\"path\");\n        StdOut.println(path(V));\n        StdOut.println();\n\n        StdOut.println(\"cycle\");\n        StdOut.println(cycle(V));\n        StdOut.println();\n\n        StdOut.println(\"binary tree\");\n        StdOut.println(binaryTree(V));\n        StdOut.println();\n\n        StdOut.println(\"tree\");\n        StdOut.println(tree(V));\n        StdOut.println();\n\n        StdOut.println(\"4-regular\");\n        StdOut.println(regular(V, 4));\n        StdOut.println();\n\n        StdOut.println(\"star\");\n        StdOut.println(star(V));\n        StdOut.println();\n\n        StdOut.println(\"wheel\");\n        StdOut.println(wheel(V));\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/GrayscalePicture.java",
    "content": "/******************************************************************************\n *  Compilation:  javac GrayscalePicture.java\n *  Execution:    java GrayscalePicture filename\n *  Dependencies: none\n *\n *  Data type for manipulating individual pixels of a grayscale image. The\n *  original image can be read from a file in JPEG, GIF, or PNG format, or the\n *  user can create a blank image of a given dimension. Includes methods for\n *  displaying the image in a window on the screen or saving to a file.\n *\n *  % java GrayscalePicture mandrill.jpg\n *\n *  Remarks\n *  -------\n *   - uses BufferedImage.TYPE_INT_RGB because BufferedImage.TYPE_BYTE_GRAY\n *     seems to do some undesirable color correction when calling getRGB() and\n *     setRGB()\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.Color;\nimport java.awt.FileDialog;\nimport java.awt.Toolkit;\n\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.awt.event.KeyEvent;\nimport java.awt.image.BufferedImage;\n\nimport javax.imageio.ImageIO;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\n\nimport javax.swing.ImageIcon;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.JPanel;\nimport javax.swing.KeyStroke;\n\n\n/**\n *  The <code>GrayscalePicture</code> data type provides a basic capability\n *  for manipulating the individual pixels of a grayscale image.\n *  The original image can be read from a {@code PNG}, {@code GIF},\n *  or {@code JPEG} file or the user can create a blank image of a given dimension.\n *  This class includes methods for displaying the image in a window on\n *  the screen or saving it to a file.\n *  <p>\n *  Pixel (<em>col</em>, <em>row</em>) is column <em>col</em> and row <em>row</em>.\n *  By default, the origin (0, 0) is the pixel in the top-left corner.\n *  These are common conventions in image processing and consistent with Java's\n *  {@link java.awt.image.BufferedImage} data type.\n *  The method {@link #setOriginLowerLeft()} change the origin to the lower left.\n *  <p>\n *  The {@code get()} and {@code set()} methods use {@link Color} objects to get\n *  or set the color of the specified pixel. The {@link Color} objects are converted\n *  to grayscale if they have different values for the R, G, and B channels.\n *  The {@code getGrayscale()} and {@code setGrayscale()} methods use an\n *  8-bit {@code int} to encode the grayscale value, thereby avoiding the need to\n *  create temporary {@code Color} objects.\n *  <p>\n *  A <em>W</em>-by-<em>H</em> picture uses ~ 4 <em>W H</em> bytes of memory,\n *  since the color of each pixel is encoded as a 32-bit <code>int</code>\n *  (even though, in principle, only ~ <em>W H</em> bytes are needed).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *  See {@link Picture} for a version that supports 32-bit RGB color images.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class GrayscalePicture implements ActionListener {\n    private BufferedImage image;               // the rasterized image\n    private JFrame frame;                      // on-screen view\n    private String title;                      // name of file\n    private boolean isOriginUpperLeft = true;  // location of origin\n    private boolean isVisible = false;         // is the frame visible?\n    private final int width, height;           // width and height\n\n   /**\n     * Creates a {@code width}-by-{@code height} picture, with {@code width} columns\n     * and {@code height} rows, where each pixel is black.\n     *\n     * @param width the width of the picture\n     * @param height the height of the picture\n     * @throws IllegalArgumentException if {@code width} is negative\n     * @throws IllegalArgumentException if {@code height} is negative\n     */\n    public GrayscalePicture(int width, int height) {\n        if (width  < 0) throw new IllegalArgumentException(\"width must be non-negative\");\n        if (height < 0) throw new IllegalArgumentException(\"height must be non-negative\");\n        this.width  = width;\n        this.height = height;\n        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\n    }\n\n   /**\n     * Creates a new grayscale picture that is a deep copy of the argument picture.\n     *\n     * @param  picture the picture to copy\n     * @throws IllegalArgumentException if {@code picture} is {@code null}\n     */\n    public GrayscalePicture(GrayscalePicture picture) {\n        if (picture == null) throw new IllegalArgumentException(\"constructor argument is null\");\n\n        width  = picture.width();\n        height = picture.height();\n        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\n        title = picture.title;\n        isOriginUpperLeft = picture.isOriginUpperLeft;\n        for (int col = 0; col < width(); col++)\n            for (int row = 0; row < height(); row++)\n                image.setRGB(col, row, picture.image.getRGB(col, row));\n    }\n\n   /**\n     * Creates a grayscale picture by reading an image from a file or URL.\n     *\n     * @param  filename the name of the file (.png, .gif, or .jpg) or URL.\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if cannot read image from file or URL\n     */\n    public GrayscalePicture(String filename) {\n        if (filename == null) throw new IllegalArgumentException(\"constructor argument is null\");\n        title = filename;\n        try {\n            // try to read from file in working directory\n            File file = new File(filename);\n            if (file.isFile()) {\n                image = ImageIO.read(file);\n            }\n\n            else {\n\n                // resource relative to .class file\n                URL url = getClass().getResource(filename);\n\n                // resource relative to classloader root\n                if (url == null) {\n                    url = getClass().getClassLoader().getResource(filename);\n                }\n\n                // or URL from web or jar\n                if (url == null) {\n                    URI uri = new URI(filename);\n                    if (uri.isAbsolute()) url = uri.toURL();\n                    else throw new IllegalArgumentException(\"could not read image: '\" + filename + \"'\");\n                }\n\n                image = ImageIO.read(url);\n            }\n\n            if (image == null) {\n                throw new IllegalArgumentException(\"could not read image: '\" + filename + \"'\");\n            }\n\n            width  = image.getWidth(null);\n            height = image.getHeight(null);\n\n            // convert to grayscale in-place\n            for (int col = 0; col < width; col++) {\n                for (int row = 0; row < height; row++) {\n                    Color color = new Color(image.getRGB(col, row));\n                    Color gray = toGray(color);\n                    image.setRGB(col, row, gray.getRGB());\n                }\n            }\n        }\n        catch (IOException | URISyntaxException e) {\n            throw new IllegalArgumentException(\"could not open image: \" + filename, e);\n        }\n    }\n\n    // Returns a grayscale version of the given color as a Color object.\n    private static Color toGray(Color color) {\n        int r = color.getRed();\n        int g = color.getGreen();\n        int b = color.getBlue();\n        int y = (int) (Math.round(0.299*r + 0.587*g + 0.114*b));\n        return new Color(y, y, y);\n    }\n\n   /**\n     * Returns a {@link JLabel} containing this picture, for embedding in a {@link JPanel},\n     * {@link JFrame} or other GUI widget.\n     *\n     * @return the {@code JLabel}\n     */\n    public JLabel getJLabel() {\n        if (image == null) return null;         // no image available\n        ImageIcon icon = new ImageIcon(image);\n        return new JLabel(icon);\n    }\n\n   /**\n     * Sets the origin to be the upper left pixel. This is the default.\n     */\n    public void setOriginUpperLeft() {\n        isOriginUpperLeft = true;\n    }\n\n   /**\n     * Sets the origin to be the lower left pixel.\n     */\n    public void setOriginLowerLeft() {\n        isOriginUpperLeft = false;\n    }\n\n   /**\n     * Displays the picture in a window on the screen.\n     */\n    public void show() {\n\n        // create the GUI for viewing the image if needed\n        if (frame == null) {\n            frame = new JFrame();\n\n            JMenuBar menuBar = new JMenuBar();\n            JMenu menu = new JMenu(\"File\");\n            menuBar.add(menu);\n            JMenuItem menuItem1 = new JMenuItem(\" Save...   \");\n            menuItem1.addActionListener(this);\n            // Java 11: use getMenuShortcutKeyMaskEx()\n            // Java 8:  use getMenuShortcutKeyMask()\n            menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,\n                                     Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));\n            menu.add(menuItem1);\n            frame.setJMenuBar(menuBar);\n\n\n\n            frame.setContentPane(getJLabel());\n            // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);\n            if (title == null) frame.setTitle(width + \"-by-\" + height);\n            else               frame.setTitle(title);\n            frame.setResizable(false);\n            frame.pack();\n        }\n\n        // draw\n        frame.setVisible(true);\n        isVisible = true;\n        frame.repaint();\n    }\n\n   /**\n     * Hides the window on the screen.\n     */\n    public void hide() {\n        if (frame != null) {\n            isVisible = false;\n            frame.setVisible(false);\n        }\n    }\n\n   /**\n     * Is the window containing the picture visible?\n     * @return {@code true} if the picture is visible, and {@code false} otherwise\n     */\n    public boolean isVisible() {\n        return isVisible;\n    }\n\n   /**\n     * Returns the height of the picture.\n     *\n     * @return the height of the picture (in pixels)\n     */\n    public int height() {\n        return height;\n    }\n\n   /**\n     * Returns the width of the picture.\n     *\n     * @return the width of the picture (in pixels)\n     */\n    public int width() {\n        return width;\n    }\n\n    private void validateRowIndex(int row) {\n        if (row < 0 || row >= height())\n            throw new IndexOutOfBoundsException(\"row index must be between 0 and \" + (height() - 1) + \": \" + row);\n    }\n\n    private void validateColumnIndex(int col) {\n        if (col < 0 || col >= width())\n            throw new IndexOutOfBoundsException(\"column index must be between 0 and \" + (width() - 1) + \": \" + col);\n    }\n\n    private void validateGrayscaleValue(int gray) {\n        if (gray < 0 || gray >= 256)\n            throw new IllegalArgumentException(\"grayscale value must be between 0 and 255\");\n    }\n\n   /**\n     * Returns the grayscale value of pixel ({@code col}, {@code row}) as a {@link java.awt.Color}.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the grayscale value of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public Color get(int col, int row) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        Color color = new Color(image.getRGB(col, row));\n        return toGray(color);\n    }\n\n   /**\n     * Returns the grayscale value of pixel ({@code col}, {@code row}) as an {@code int}\n     * between 0 and 255.\n     * Using this method can be more efficient than {@link #get(int, int)} because\n     * it does not create a {@code Color} object.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the 8-bit integer representation of the grayscale value of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public int getGrayscale(int col, int row) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        if (isOriginUpperLeft) return image.getRGB(col, row) & 0xFF;\n        else                   return image.getRGB(col, height - row - 1) & 0xFF;\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given grayscale value.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param color the color (converts to grayscale if color is not a shade of gray)\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     * @throws IllegalArgumentException if {@code color} is {@code null}\n     */\n    public void set(int col, int row, Color color) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        if (color == null) throw new IllegalArgumentException(\"color argument is null\");\n        Color gray = toGray(color);\n        image.setRGB(col, row, gray.getRGB());\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given grayscale value\n     * between 0 and 255.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param gray the 8-bit integer representation of the grayscale value\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public void setGrayscale(int col, int row, int gray) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        validateGrayscaleValue(gray);\n        int rgb = gray | (gray << 8) | (gray << 16);\n        if (isOriginUpperLeft) image.setRGB(col, row, rgb);\n        else                   image.setRGB(col, height - row - 1, rgb);\n    }\n\n   /**\n     * Returns true if this picture is equal to the argument picture.\n     *\n     * @param other the other picture\n     * @return {@code true} if this picture is the same dimension as {@code other}\n     *         and if all pixels have the same color; {@code false} otherwise\n     */\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        GrayscalePicture that = (GrayscalePicture) other;\n        if (this.width()  != that.width())  return false;\n        if (this.height() != that.height()) return false;\n        for (int col = 0; col < width(); col++)\n            for (int row = 0; row < height(); row++)\n                if (this.getGrayscale(col, row) != that.getGrayscale(col, row)) return false;\n        return true;\n    }\n\n   /**\n     * Returns a string representation of this picture.\n     * The result is a <code>width</code>-by-<code>height</code> matrix of pixels,\n     * where the grayscale value of a pixel is an integer between 0 and 255.\n     *\n     * @return a string representation of this picture\n     */\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(width +\"-by-\" + height + \" grayscale picture (grayscale values given in hex)\\n\");\n        for (int row = 0; row < height; row++) {\n            for (int col = 0; col < width; col++) {\n                int gray;\n                if (isOriginUpperLeft) gray = 0xFF & image.getRGB(col, row);\n                else                   gray = 0xFF & image.getRGB(col, height - row - 1);\n                sb.append(String.format(\"%3d \", gray));\n            }\n            sb.append(\"\\n\");\n        }\n        return sb.toString().trim();\n    }\n\n    /**\n     * This operation is not supported because pictures are mutable.\n     *\n     * @return does not return a value\n     * @throws UnsupportedOperationException if called\n     */\n    public int hashCode() {\n        throw new UnsupportedOperationException(\"hashCode() is not supported because pictures are mutable\");\n    }\n\n   /**\n     * Saves the picture to a file in either PNG or JPEG format.\n     * The filetype extension must be either .png or .jpg.\n     *\n     * @param  filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if {@code filename} has invalid filetype extension\n     * @throws IllegalArgumentException if cannot write the file {@code filename}\n     */\n    public void save(String filename) {\n        if (filename == null) throw new IllegalArgumentException(\"argument to save() is null\");\n        save(new File(filename));\n        title = filename;\n    }\n\n   /**\n     * Saves the picture to a file in a PNG or JPEG image format.\n     *\n     * @param  file the file\n     * @throws IllegalArgumentException if {@code file} is {@code null}\n     */\n    public void save(File file) {\n        if (file == null) throw new IllegalArgumentException(\"argument to save() is null\");\n        title = file.getName();\n        if (frame != null) frame.setTitle(title);\n\n        String suffix = title.substring(title.lastIndexOf('.') + 1);\n        if (!title.contains(\".\") || suffix.length() == 0) {\n            System.out.printf(\"Error: the filename '%s' has no file extension, such as .jpg or .png\\n\", title);\n            return;\n        }\n\n        try {\n            // for formats that support transparency (e.g., PNG and GIF)\n            if (ImageIO.write(image, suffix, file)) return;\n\n            // for formats that don't support transparency (e.g., JPG and BMP)\n            // create BufferedImage in RGB format and use white background\n            BufferedImage imageRGB = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\n            imageRGB.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);\n            if (ImageIO.write(imageRGB, suffix, file)) return;\n\n            // failed to save the file; probably wrong format\n            throw new IllegalArgumentException(\"The filetype '\" + suffix + \"' is not supported\");\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not write file '\" + title + \"'\", e);\n        }\n    }\n\n   /**\n     * Opens a save dialog box when the user selects \"Save As\" from the menu.\n     */\n    @Override\n    public void actionPerformed(ActionEvent event) {\n        FileDialog chooser = new FileDialog(frame,\n                             \"Use a .png or .jpg extension\", FileDialog.SAVE);\n        chooser.setVisible(true);\n        String selectedDirectory = chooser.getDirectory();\n        String selectedFilename = chooser.getFile();\n        if (selectedDirectory != null && selectedFilename != null) {\n            try {\n                save(selectedDirectory + selectedFilename);\n            }\n            catch (IllegalArgumentException e) {\n                System.err.println(e.getMessage());\n            }\n        }\n    }\n\n   /**\n     * Unit tests this {@code Picture} data type.\n     * Reads a picture specified by the command-line argument,\n     * and shows it in a window on the screen.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        GrayscalePicture picture = new GrayscalePicture(args[0]);\n        StdOut.printf(\"%d-by-%d\\n\", picture.width(), picture.height());\n        GrayscalePicture copy = new GrayscalePicture(picture);\n        picture.show();\n        copy.show();\n        while (!StdIn.isEmpty()) {\n            int row = StdIn.readInt();\n            int col = StdIn.readInt();\n            int gray = StdIn.readInt();\n            picture.setGrayscale(row, col, gray);\n            StdOut.println(picture.get(row, col));\n            StdOut.println(picture.getGrayscale(row, col));\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Heap.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Heap.java\n *  Execution:    java Heap < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/24pq/tiny.txt\n *                https://algs4.cs.princeton.edu/24pq/words3.txt\n *\n *  Sorts a sequence of strings from standard input using heapsort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Heap < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Heap < words3.txt\n *  all bad bed bug dad ... yes yet zoo   [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Heap} class provides a static method to sort an array\n *  using <em>heapsort</em>.\n *  <p>\n *  This implementation takes &Theta;(<em>n</em> log <em>n</em>) time\n *  to sort any array of length <em>n</em> (assuming comparisons\n *  take constant time). It makes at most\n *  2 <em>n</em> log<sub>2</sub> <em>n</em> compares.\n *  <p>\n *  This sorting algorithm is not stable.\n *  It uses &Theta;(1) extra memory (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Heap {\n\n    // This class should not be instantiated.\n    private Heap() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param pq the array to be sorted\n     */\n    public static void sort(Comparable[] pq) {\n        int n = pq.length;\n\n        // heapify phase\n        for (int k = n/2; k >= 1; k--)\n            sink(pq, k, n);\n\n        // sortdown phase\n        int k = n;\n        while (k > 1) {\n            exch(pq, 1, k--);\n            sink(pq, 1, k);\n        }\n    }\n\n   /***************************************************************************\n    * Helper functions to restore the heap invariant.\n    ***************************************************************************/\n\n    private static void sink(Comparable[] pq, int k, int n) {\n        while (2*k <= n) {\n            int j = 2*k;\n            if (j < n && less(pq, j, j+1)) j++;\n            if (!less(pq, k, j)) break;\n            exch(pq, k, j);\n            k = j;\n        }\n    }\n\n   /***************************************************************************\n    * Helper functions for comparisons and swaps.\n    * Indices are \"off-by-one\" to support 1-based indexing.\n    ***************************************************************************/\n    private static boolean less(Comparable[] pq, int i, int j) {\n        return pq[i-1].compareTo(pq[j-1]) < 0;\n    }\n\n    private static void exch(Object[] pq, int i, int j) {\n        Object swap = pq[i-1];\n        pq[i-1] = pq[j-1];\n        pq[j-1] = swap;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; heapsorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Heap.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/HexDump.java",
    "content": "/******************************************************************************\n *  Compilation:  javac HexDump.java\n *  Execution:    java HexDump < file\n *  Dependencies: BinaryStdIn.java StdOut.java\n *  Data file:    https://algs4.cs.princeton.edu/55compression/abra.txt\n *\n *  Reads in a binary file and writes out the bytes in hex, 16 per line.\n *\n *  % more abra.txt\n *  ABRACADABRA!\n *\n *  % java HexDump 16 < abra.txt\n *  41 42 52 41 43 41 44 41 42 52 41 21\n *  96 bits\n *\n *\n *  Remark\n *  --------------------------\n *   - Similar to the Unix utilities od (octal dump) or hexdump (hexadecimal dump).\n *\n *  % od -t x1 < abra.txt\n *  0000000 41 42 52 41 43 41 44 41 42 52 41 21\n *  0000014\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code HexDump} class provides a client for displaying the contents\n *  of a binary file in hexadecimal.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  <p>\n *  See also {@link BinaryDump} and {@link PictureDump}.\n *  For more full-featured versions, see the Unix utilities\n *  {@code od} (octal dump) and {@code hexdump} (hexadecimal dump).\n *  <p>\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class HexDump {\n\n    // Do not instantiate.\n    private HexDump() { }\n\n    /**\n     * Reads in a sequence of bytes from standard input and writes\n     * them to standard output using hexadecimal notation, k hex digits\n     * per line, where k is given as a command-line integer (defaults\n     * to 16 if no integer is specified); also writes the number\n     * of bits.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int bytesPerLine = 16;\n        if (args.length == 1) {\n            bytesPerLine = Integer.parseInt(args[0]);\n        }\n\n        int i;\n        for (i = 0; !BinaryStdIn.isEmpty(); i++) {\n            if (bytesPerLine == 0) {\n                BinaryStdIn.readChar();\n                continue;\n            }\n            if (i == 0) StdOut.printf(\"\");\n            else if (i % bytesPerLine == 0) StdOut.printf(\"\\n\", i);\n            else StdOut.print(\" \");\n            char c = BinaryStdIn.readChar();\n            StdOut.printf(\"%02x\", c & 0xff);\n        }\n        if (bytesPerLine != 0) StdOut.println();\n        StdOut.println((i*8) + \" bits\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/HopcroftKarp.java",
    "content": "/******************************************************************************\n *  Compilation:  javac HopcroftKarp.java\n *  Execution:    java HopcroftKarp V1 V2 E\n *  Dependencies: FordFulkerson.java FlowNetwork.java FlowEdge.java\n *                BipartiteX.java\n *\n *  Find a maximum cardinality matching (and minimum cardinality vertex cover)\n *  in a bipartite graph using Hopcroft-Karp algorithm.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code HopcroftKarp} class represents a data type for computing a\n *  <em>maximum (cardinality) matching</em> and a\n *  <em>minimum (cardinality) vertex cover</em> in a bipartite graph.\n *  A <em>bipartite graph</em> in a graph whose vertices can be partitioned\n *  into two disjoint sets such that every edge has one endpoint in either set.\n *  A <em>matching</em> in a graph is a subset of its edges with no common\n *  vertices. A <em>maximum matching</em> is a matching with the maximum number\n *  of edges.\n *  A <em>perfect matching</em> is a matching which matches all vertices in the graph.\n *  A <em>vertex cover</em> in a graph is a subset of its vertices such that\n *  every edge is incident to at least one vertex. A <em>minimum vertex cover</em>\n *  is a vertex cover with the minimum number of vertices.\n *  By Konig's theorem, in any bipartite\n *  graph, the maximum number of edges in matching equals the minimum number\n *  of vertices in a vertex cover.\n *  The maximum matching problem in <em>nonbipartite</em> graphs is\n *  also important, but all known algorithms for this more general problem\n *  are substantially more complicated.\n *  <p>\n *  This implementation uses the <em>Hopcroft-Karp algorithm</em>.\n *  The order of growth of the running time in the worst case is\n *  (<em>E</em> + <em>V</em>) sqrt(<em>V</em>),\n *  where <em>E</em> is the number of edges and <em>V</em> is the number\n *  of vertices in the graph. It uses extra space (not including the graph)\n *  proportional to <em>V</em>.\n *  <p>\n *  See also {@link BipartiteMatching}, which solves the problem in\n *  O(<em>E V</em>) time using the <em>alternating path algorithm</em>\n *  and <a href = \"https://algs4.cs.princeton.edu/65reductions/BipartiteMatchingToMaxflow.java.html\">BipartiteMatchingToMaxflow</a>,\n *  which solves the problem in O(<em>E V</em>) time via a reduction\n *  to the maxflow problem.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/65reductions\">Section 6.5</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class HopcroftKarp {\n    private static final int UNMATCHED = -1;\n\n    private final int V;                 // number of vertices in the graph\n    private BipartiteX bipartition;      // the bipartition\n    private int cardinality;             // cardinality of current matching\n    private int[] mate;                  // mate[v] =  w if v-w is an edge in current matching\n                                         //         = -1 if v is not in current matching\n    private boolean[] inMinVertexCover;  // inMinVertexCover[v] = true iff v is in min vertex cover\n    private boolean[] marked;            // marked[v] = true iff v is reachable via alternating path\n    private int[] distTo;                // distTo[v] = number of edges on shortest path to v\n\n    /**\n     * Determines a maximum matching (and a minimum vertex cover)\n     * in a bipartite graph.\n     *\n     * @param  G the bipartite graph\n     * @throws IllegalArgumentException if {@code G} is not bipartite\n     */\n    public HopcroftKarp(Graph G) {\n        bipartition = new BipartiteX(G);\n        if (!bipartition.isBipartite()) {\n            throw new IllegalArgumentException(\"graph is not bipartite\");\n        }\n\n        // initialize empty matching\n        this.V = G.V();\n        mate = new int[V];\n        for (int v = 0; v < V; v++)\n            mate[v] = UNMATCHED;\n\n        // the call to hasAugmentingPath() provides enough info to reconstruct level graph\n        while (hasAugmentingPath(G)) {\n\n            // to be able to iterate over each adjacency list, keeping track of which\n            // vertex in each adjacency list needs to be explored next\n            Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];\n            for (int v = 0; v < G.V(); v++)\n                adj[v] = G.adj(v).iterator();\n\n            // for each unmatched vertex s on one side of bipartition\n            for (int s = 0; s < V; s++) {\n                if (isMatched(s) || !bipartition.color(s)) continue;   // or use distTo[s] == 0\n\n                // find augmenting path from s using nonrecursive DFS\n                Stack<Integer> path = new Stack<Integer>();\n                path.push(s);\n                while (!path.isEmpty()) {\n                    int v = path.peek();\n\n                    // retreat, no more edges in level graph leaving v\n                    if (!adj[v].hasNext())\n                        path.pop();\n\n                    // advance\n                    else {\n                        // process edge v-w only if it is an edge in level graph\n                        int w = adj[v].next();\n                        if (!isLevelGraphEdge(v, w)) continue;\n\n                        // add w to augmenting path\n                        path.push(w);\n\n                        // augmenting path found: update the matching\n                        if (!isMatched(w)) {\n                            // StdOut.println(\"augmenting path: \" + toString(path));\n\n                            while (!path.isEmpty()) {\n                                int x = path.pop();\n                                int y = path.pop();\n                                mate[x] = y;\n                                mate[y] = x;\n                            }\n                            cardinality++;\n                        }\n                    }\n                }\n            }\n        }\n\n        // also find a min vertex cover\n        inMinVertexCover = new boolean[V];\n        for (int v = 0; v < V; v++) {\n            if (bipartition.color(v) && !marked[v]) inMinVertexCover[v] = true;\n            if (!bipartition.color(v) && marked[v]) inMinVertexCover[v] = true;\n        }\n\n        assert certifySolution(G);\n    }\n\n    // string representation of augmenting path (chop off last vertex)\n    private static String toString(Iterable<Integer> path) {\n        StringBuilder sb = new StringBuilder();\n        for (int v : path)\n            sb.append(v + \"-\");\n        String s = sb.toString();\n        s = s.substring(0, s.lastIndexOf('-'));\n        return s;\n    }\n\n   // is the edge v-w in the level graph?\n    private boolean isLevelGraphEdge(int v, int w) {\n        return (distTo[w] == distTo[v] + 1) && isResidualGraphEdge(v, w);\n    }\n\n   // is the edge v-w a forward edge not in the matching or a reverse edge in the matching?\n    private boolean isResidualGraphEdge(int v, int w) {\n        if ((mate[v] != w) &&  bipartition.color(v)) return true;\n        if ((mate[v] == w) && !bipartition.color(v)) return true;\n        return false;\n    }\n\n    /*\n     * is there an augmenting path?\n     *   - if so, upon termination adj[] contains the level graph;\n     *   - if not, upon termination marked[] specifies those vertices reachable via an alternating\n     *     path from one side of the bipartition\n     *\n     * an alternating path is a path whose edges belong alternately to the matching and not\n     * to the matching\n     *\n     * an augmenting path is an alternating path that starts and ends at unmatched vertices\n     */\n    private boolean hasAugmentingPath(Graph G) {\n\n        // shortest path distances\n        marked = new boolean[V];\n        distTo = new int[V];\n        for (int v = 0; v < V; v++)\n            distTo[v] = Integer.MAX_VALUE;\n\n        // breadth-first search (starting from all unmatched vertices on one side of bipartition)\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int v = 0; v < V; v++) {\n            if (bipartition.color(v) && !isMatched(v)) {\n                queue.enqueue(v);\n                marked[v] = true;\n                distTo[v] = 0;\n            }\n        }\n\n        // run BFS until an augmenting path is found\n        // (and keep going until all vertices at that distance are explored)\n        boolean hasAugmentingPath = false;\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            for (int w : G.adj(v)) {\n\n                // forward edge not in matching or backwards edge in matching\n                if (isResidualGraphEdge(v, w)) {\n                    if (!marked[w]) {\n                        distTo[w] = distTo[v] + 1;\n                        marked[w] = true;\n                        if (!isMatched(w))\n                            hasAugmentingPath = true;\n\n                        // stop enqueuing vertices once an alternating path has been discovered\n                        // (no vertex on same side will be marked if its shortest path distance longer)\n                        if (!hasAugmentingPath) queue.enqueue(w);\n                    }\n                }\n            }\n        }\n\n        return hasAugmentingPath;\n    }\n\n    /**\n     * Returns the vertex to which the specified vertex is matched in\n     * the maximum matching computed by the algorithm.\n     *\n     * @param  v the vertex\n     * @return the vertex to which vertex {@code v} is matched in the\n     *         maximum matching; {@code -1} if the vertex is not matched\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     *\n     */\n    public int mate(int v) {\n        validate(v);\n        return mate[v];\n    }\n\n    /**\n     * Returns true if the specified vertex is matched in the maximum matching\n     * computed by the algorithm.\n     *\n     * @param  v the vertex\n     * @return {@code true} if vertex {@code v} is matched in maximum matching;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     *\n     */\n    public boolean isMatched(int v) {\n        validate(v);\n        return mate[v] != UNMATCHED;\n    }\n\n    /**\n     * Returns the number of edges in any maximum matching.\n     *\n     * @return the number of edges in any maximum matching\n     */\n    public int size() {\n        return cardinality;\n    }\n\n    /**\n     * Returns true if the graph contains a perfect matching.\n     * That is, the number of edges in a maximum matching is equal to one half\n     * of the number of vertices in the graph (so that every vertex is matched).\n     *\n     * @return {@code true} if the graph contains a perfect matching;\n     *         {@code false} otherwise\n     */\n    public boolean isPerfect() {\n        return cardinality * 2 == V;\n    }\n\n    /**\n     * Returns true if the specified vertex is in the minimum vertex cover\n     * computed by the algorithm.\n     *\n     * @param  v the vertex\n     * @return {@code true} if vertex {@code v} is in the minimum vertex cover;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean inMinVertexCover(int v) {\n        validate(v);\n        return inMinVertexCover[v];\n    }\n\n    // throw an exception if vertex is invalid\n    private void validate(int v) {\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // check that mate[] and inVertexCover[] define a max matching and min vertex cover, respectively\n    private boolean certifySolution(Graph G) {\n\n        // check that mate(v) = w iff mate(w) = v\n        for (int v = 0; v < V; v++) {\n            if (mate(v) == -1) continue;\n            if (mate(mate(v)) != v) return false;\n        }\n\n        // check that size() is consistent with mate()\n        int matchedVertices = 0;\n        for (int v = 0; v < V; v++) {\n            if (mate(v) != -1) matchedVertices++;\n        }\n        if (2*size() != matchedVertices) return false;\n\n        // check that size() is consistent with minVertexCover()\n        int sizeOfMinVertexCover = 0;\n        for (int v = 0; v < V; v++)\n            if (inMinVertexCover(v)) sizeOfMinVertexCover++;\n        if (size() != sizeOfMinVertexCover) return false;\n\n        // check that mate() uses each vertex at most once\n        boolean[] isMatched = new boolean[V];\n        for (int v = 0; v < V; v++) {\n            int w = mate[v];\n            if (w == -1) continue;\n            if (v == w) return false;\n            if (v >= w) continue;\n            if (isMatched[v] || isMatched[w]) return false;\n            isMatched[v] = true;\n            isMatched[w] = true;\n        }\n\n        // check that mate() uses only edges that appear in the graph\n        for (int v = 0; v < V; v++) {\n            if (mate(v) == -1) continue;\n            boolean isEdge = false;\n            for (int w : G.adj(v)) {\n                if (mate(v) == w) isEdge = true;\n            }\n            if (!isEdge) return false;\n        }\n\n        // check that inMinVertexCover() is a vertex cover\n        for (int v = 0; v < V; v++)\n            for (int w : G.adj(v))\n                if (!inMinVertexCover(v) && !inMinVertexCover(w)) return false;\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code HopcroftKarp} data type.\n     * Takes three command-line arguments {@code V1}, {@code V2}, and {@code E};\n     * creates a random bipartite graph with {@code V1} + {@code V2} vertices\n     * and {@code E} edges; computes a maximum matching and minimum vertex cover;\n     * and prints the results.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        int V1 = Integer.parseInt(args[0]);\n        int V2 = Integer.parseInt(args[1]);\n        int E  = Integer.parseInt(args[2]);\n        Graph G = GraphGenerator.bipartite(V1, V2, E);\n        if (G.V() < 1000) StdOut.println(G);\n\n        HopcroftKarp matching = new HopcroftKarp(G);\n\n        // print maximum matching\n        StdOut.printf(\"Number of edges in max matching        = %d\\n\", matching.size());\n        StdOut.printf(\"Number of vertices in min vertex cover = %d\\n\", matching.size());\n        StdOut.printf(\"Graph has a perfect matching           = %b\\n\", matching.isPerfect());\n        StdOut.println();\n\n        if (G.V() >= 1000) return;\n\n        StdOut.print(\"Max matching: \");\n        for (int v = 0; v < G.V(); v++) {\n            int w = matching.mate(v);\n            if (matching.isMatched(v) && v < w)  // print each edge only once\n                StdOut.print(v + \"-\" + w + \" \");\n        }\n        StdOut.println();\n\n        // print minimum vertex cover\n        StdOut.print(\"Min vertex cover: \");\n        for (int v = 0; v < G.V(); v++)\n            if (matching.inMinVertexCover(v))\n                StdOut.print(v + \" \");\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Huffman.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Huffman.java\n *  Execution:    java Huffman - < input.txt   (compress)\n *  Execution:    java Huffman + < input.txt   (expand)\n *  Dependencies: BinaryIn.java BinaryOut.java\n *  Data files:   https://algs4.cs.princeton.edu/55compression/abra.txt\n *                https://algs4.cs.princeton.edu/55compression/tinytinyTale.txt\n *                https://algs4.cs.princeton.edu/55compression/medTale.txt\n *                https://algs4.cs.princeton.edu/55compression/tale.txt\n *\n *  Compress or expand a binary input stream using the Huffman algorithm.\n *\n *  % java Huffman - < abra.txt | java BinaryDump 60\n *  010100000100101000100010010000110100001101010100101010000100\n *  000000000000000000000000000110001111100101101000111110010100\n *  120 bits\n *\n *  % java Huffman - < abra.txt | java Huffman +\n *  ABRACADABRA!\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Huffman} class provides static methods for compressing\n *  and expanding a binary input using Huffman codes over the 8-bit extended\n *  ASCII alphabet.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Huffman {\n\n    // alphabet size of extended ASCII\n    private static final int R = 256;\n\n    // Do not instantiate.\n    private Huffman() { }\n\n    // Huffman trie node\n    private static class Node implements Comparable<Node> {\n        private final char ch;\n        private final int freq;\n        private final Node left, right;\n\n        Node(char ch, int freq, Node left, Node right) {\n            this.ch    = ch;\n            this.freq  = freq;\n            this.left  = left;\n            this.right = right;\n        }\n\n        // is the node a leaf node?\n        private boolean isLeaf() {\n            assert ((left == null) && (right == null)) || ((left != null) && (right != null));\n            return (left == null) && (right == null);\n        }\n\n        // compare, based on frequency\n        public int compareTo(Node that) {\n            return this.freq - that.freq;\n        }\n    }\n\n    /**\n     * Reads a sequence of 8-bit bytes from standard input; compresses them\n     * using Huffman codes with an 8-bit alphabet; and writes the results\n     * to standard output.\n     */\n    public static void compress() {\n        // read the input\n        String s = BinaryStdIn.readString();\n        char[] input = s.toCharArray();\n\n        // tabulate frequency counts\n        int[] freq = new int[R];\n        for (int i = 0; i < input.length; i++)\n            freq[input[i]]++;\n\n        // build Huffman trie\n        Node root = buildTrie(freq);\n\n        // build code table\n        String[] st = new String[R];\n        buildCode(st, root, \"\");\n\n        // print trie for decoder\n        writeTrie(root);\n\n        // print number of bytes in original uncompressed message\n        BinaryStdOut.write(input.length);\n\n        // use Huffman code to encode input\n        for (int i = 0; i < input.length; i++) {\n            String code = st[input[i]];\n            for (int j = 0; j < code.length(); j++) {\n                if (code.charAt(j) == '0') {\n                    BinaryStdOut.write(false);\n                }\n                else if (code.charAt(j) == '1') {\n                    BinaryStdOut.write(true);\n                }\n                else throw new IllegalStateException(\"Illegal state\");\n            }\n        }\n\n        // close output stream\n        BinaryStdOut.close();\n    }\n\n    // build the Huffman trie given frequencies\n    private static Node buildTrie(int[] freq) {\n\n        // initialize priority queue with singleton trees\n        MinPQ<Node> pq = new MinPQ<Node>();\n        for (char c = 0; c < R; c++)\n            if (freq[c] > 0)\n                pq.insert(new Node(c, freq[c], null, null));\n\n        // merge two smallest trees\n        while (pq.size() > 1) {\n            Node left  = pq.delMin();\n            Node right = pq.delMin();\n            Node parent = new Node('\\0', left.freq + right.freq, left, right);\n            pq.insert(parent);\n        }\n        return pq.delMin();\n    }\n\n\n    // write bitstring-encoded trie to standard output\n    private static void writeTrie(Node x) {\n        if (x.isLeaf()) {\n            BinaryStdOut.write(true);\n            BinaryStdOut.write(x.ch, 8);\n            return;\n        }\n        BinaryStdOut.write(false);\n        writeTrie(x.left);\n        writeTrie(x.right);\n    }\n\n    // make a lookup table from symbols and their encodings\n    private static void buildCode(String[] st, Node x, String s) {\n        if (!x.isLeaf()) {\n            buildCode(st, x.left,  s + '0');\n            buildCode(st, x.right, s + '1');\n        }\n        else {\n            st[x.ch] = s;\n        }\n    }\n\n    /**\n     * Reads a sequence of bits that represents a Huffman-compressed message from\n     * standard input; expands them; and writes the results to standard output.\n     */\n    public static void expand() {\n\n        // read in Huffman trie from input stream\n        Node root = readTrie();\n\n        // number of bytes to write\n        int length = BinaryStdIn.readInt();\n\n        // decode using the Huffman trie\n        for (int i = 0; i < length; i++) {\n            Node x = root;\n            while (!x.isLeaf()) {\n                boolean bit = BinaryStdIn.readBoolean();\n                if (bit) x = x.right;\n                else     x = x.left;\n            }\n            BinaryStdOut.write(x.ch, 8);\n        }\n        BinaryStdOut.close();\n    }\n\n\n    private static Node readTrie() {\n        boolean isLeaf = BinaryStdIn.readBoolean();\n        if (isLeaf) {\n            return new Node(BinaryStdIn.readChar(), -1, null, null);\n        }\n        else {\n            return new Node('\\0', -1, readTrie(), readTrie());\n        }\n    }\n\n    /**\n     * Sample client that calls {@code compress()} if the command-line\n     * argument is \"-\" an {@code expand()} if it is \"+\".\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        if      (args[0].equals(\"-\")) compress();\n        else if (args[0].equals(\"+\")) expand();\n        else throw new IllegalArgumentException(\"Illegal command line argument\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/In.java",
    "content": "/******************************************************************************\n *  Compilation:  javac In.java\n *  Execution:    java In   (basic test --- see source for required files)\n *  Dependencies: none\n *\n *  Reads in data of various types from standard input, files, and URLs.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.BufferedInputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.Socket;\nimport java.net.URL;\nimport java.net.URLConnection;\n\nimport java.util.ArrayList;\nimport java.util.InputMismatchException;\nimport java.util.Locale;\nimport java.util.NoSuchElementException;\nimport java.util.Scanner;\nimport java.util.regex.Pattern;\n\n/**\n *  The <code>In</code> data type provides methods for reading strings\n *  and numbers from standard input, file input, URLs, and sockets.\n *  <p>\n *  The Locale used is: language = English, country = US. This is consistent\n *  with the formatting conventions with Java floating-point literals,\n *  command-line arguments (via {@link Double#parseDouble(String)})\n *  and standard output.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *  <p>\n *  Like {@link Scanner}, reading a token also consumes preceding Java\n *  whitespace, reading a full line consumes\n *  the following end-of-line delimiter, while reading a character consumes\n *  nothing extra.\n *  <p>\n *  Whitespace is defined in {@link Character#isWhitespace(char)}. Newlines\n *  consist of \\n, \\r, \\r\\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;\n *  see <a href=\"http://www.docjar.com/html/api/java/util/Scanner.java.html\">\n *  Scanner.java</a> (NB: Java 6u23 and earlier uses only \\r, \\r, \\r\\n).\n *\n *  @author David Pritchard\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class In {\n\n    ///// begin: section (1 of 2) of code duplicated from In to StdIn.\n\n    // assume Unicode UTF-8 encoding\n    private static final String CHARSET_NAME = \"UTF-8\";\n\n    // assume language = English, country = US for consistency with System.out.\n    private static final Locale LOCALE = Locale.US;\n\n    // the default token separator; we maintain the invariant that this value\n    // is held by the scanner's delimiter between calls\n    private static final Pattern WHITESPACE_PATTERN = Pattern.compile(\"\\\\p{javaWhitespace}+\");\n\n    // makes whitespace characters significant\n    private static final Pattern EMPTY_PATTERN = Pattern.compile(\"\");\n\n    // used to read the entire input. source:\n    // http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html\n    private static final Pattern EVERYTHING_PATTERN = Pattern.compile(\"\\\\A\");\n\n    //// end: section (1 of 2) of code duplicated from In to StdIn.\n\n    private Scanner scanner;\n\n   /**\n     * Initializes an input stream from standard input.\n     */\n    public In() {\n        scanner = new Scanner(new BufferedInputStream(System.in), CHARSET_NAME);\n        scanner.useLocale(LOCALE);\n    }\n\n   /**\n     * Initializes an input stream from a socket.\n     *\n     * @param  socket the socket\n     * @throws IllegalArgumentException if cannot open {@code socket}\n     * @throws IllegalArgumentException if {@code socket} is {@code null}\n     */\n    public In(Socket socket) {\n        if (socket == null) throw new IllegalArgumentException(\"socket argument is null\");\n        try {\n            InputStream is = socket.getInputStream();\n            scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);\n            scanner.useLocale(LOCALE);\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"could not open socket: \" + socket, ioe);\n        }\n    }\n\n   /**\n     * Initializes an input stream from a URL.\n     *\n     * @param  url the URL\n     * @throws IllegalArgumentException if cannot open {@code url}\n     * @throws IllegalArgumentException if {@code url} is {@code null}\n     */\n    public In(URL url) {\n        if (url == null) throw new IllegalArgumentException(\"url argument is null\");\n        try {\n            URLConnection site = url.openConnection();\n            InputStream is     = site.getInputStream();\n            scanner            = new Scanner(new BufferedInputStream(is), CHARSET_NAME);\n            scanner.useLocale(LOCALE);\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"could not read URL: '\" + url + \"'\", ioe);\n        }\n    }\n\n   /**\n     * Initializes an input stream from a file.\n     *\n     * @param  file the file\n     * @throws IllegalArgumentException if cannot open {@code file}\n     * @throws IllegalArgumentException if {@code file} is {@code null}\n     */\n    public In(File file) {\n        if (file == null) throw new IllegalArgumentException(\"file argument is null\");\n        try {\n            // for consistency with StdIn, wrap with BufferedInputStream instead of use\n            // file as argument to Scanner\n            FileInputStream fis = new FileInputStream(file);\n            scanner = new Scanner(new BufferedInputStream(fis), CHARSET_NAME);\n            scanner.useLocale(LOCALE);\n        }\n        catch (IOException ioe) {;\n            throw new IllegalArgumentException(\"could not read file: \" + file, ioe);\n        }\n    }\n\n\n   /**\n     * Initializes an input stream from a filename or web page name.\n     *\n     * @param  name the filename or web page name\n     * @throws IllegalArgumentException if cannot open {@code name} as\n     *         a file or URL\n     * @throws IllegalArgumentException if {@code name} is {@code null}\n     */\n    public In(String name) {\n        if (name == null) throw new IllegalArgumentException(\"argument is null\");\n        if (name.length() == 0) throw new IllegalArgumentException(\"argument is the empty string\");\n        try {\n            // first try to read file from local file system\n            File file = new File(name);\n            if (file.exists()) {\n                // for consistency with StdIn, wrap with BufferedInputStream instead of use\n                // file as argument to Scanner\n                FileInputStream fis = new FileInputStream(file);\n                scanner = new Scanner(new BufferedInputStream(fis), CHARSET_NAME);\n                scanner.useLocale(LOCALE);\n                return;\n            }\n\n            // resource relative to .class file\n            URL url = getClass().getResource(name);\n\n            // resource relative to classloader root\n            if (url == null) {\n                url = getClass().getClassLoader().getResource(name);\n            }\n\n            // or URL from web\n            if (url == null) {\n                URI uri = new URI(name);\n                if (uri.isAbsolute()) url = uri.toURL();\n                else throw new IllegalArgumentException(\"could not read: '\" + name + \"'\");\n                url = new URL(name);\n            }\n\n            URLConnection site = url.openConnection();\n\n            // in order to set User-Agent, replace above line with these two\n            // HttpURLConnection site = (HttpURLConnection) url.openConnection();\n            // site.addRequestProperty(\"User-Agent\", \"Mozilla/4.76\");\n\n            InputStream is     = site.getInputStream();\n            scanner            = new Scanner(new BufferedInputStream(is), CHARSET_NAME);\n            scanner.useLocale(LOCALE);\n        }\n        catch (IOException | URISyntaxException e) {\n            throw new IllegalArgumentException(\"could not read: '\" + name + \"'\");\n        }\n    }\n\n    /**\n     * Initializes an input stream from a given {@link Scanner} source; use with\n     * {@code new Scanner(String)} to read from a string.\n     * <p>\n     * Note that this does not create a defensive copy, so the\n     * scanner will be mutated as you read on.\n     *\n     * @param  scanner the scanner\n     * @throws IllegalArgumentException if {@code scanner} is {@code null}\n     */\n    public In(Scanner scanner) {\n        if (scanner == null) throw new IllegalArgumentException(\"scanner argument is null\");\n        this.scanner = scanner;\n    }\n\n    /**\n     * Returns true if this input stream exists.\n     *\n     * @return {@code true} if this input stream exists; {@code false} otherwise\n     */\n    public boolean exists()  {\n        return scanner != null;\n    }\n\n    ////  begin: section (2 of 2) of code duplicated from In to StdIn,\n    ////  with all methods changed from \"public\" to \"public static\".\n\n   /**\n     * Returns true if input stream is empty (except possibly whitespace).\n     * Use this to know whether the next call to {@link #readString()},\n     * {@link #readDouble()}, etc. will succeed.\n     *\n     * @return {@code true} if this input stream is empty (except possibly whitespace);\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return !scanner.hasNext();\n    }\n\n   /**\n     * Returns true if this input stream has a next line.\n     * Use this method to know whether the\n     * next call to {@link #readLine()} will succeed.\n     * This method is functionally equivalent to {@link #hasNextChar()}.\n     *\n     * @return {@code true} if this input stream has more input (including whitespace);\n     *         {@code false} otherwise\n     */\n    public boolean hasNextLine() {\n        return scanner.hasNextLine();\n    }\n\n    /**\n     * Returns true if this input stream has more input (including whitespace).\n     * Use this method to know whether the next call to {@link #readChar()} will succeed.\n     * This method is functionally equivalent to {@link #hasNextLine()}.\n     *\n     * @return {@code true} if this input stream has more input (including whitespace);\n     *         {@code false} otherwise\n     */\n    public boolean hasNextChar() {\n        scanner.useDelimiter(EMPTY_PATTERN);\n        boolean result = scanner.hasNext();\n        scanner.useDelimiter(WHITESPACE_PATTERN);\n        return result;\n    }\n\n\n   /**\n     * Reads and returns the next line in this input stream.\n     *\n     * @return the next line in this input stream; {@code null} if no such line\n     */\n    public String readLine() {\n        String line;\n        try {\n            line = scanner.nextLine();\n        }\n        catch (NoSuchElementException e) {\n            line = null;\n        }\n        return line;\n    }\n\n    /**\n     * Reads and returns the next character in this input stream.\n     *\n     * @return the next {@code char} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     */\n    public char readChar() {\n        scanner.useDelimiter(EMPTY_PATTERN);\n        try {\n            String ch = scanner.next();\n            assert ch.length() == 1 : \"Internal (Std)In.readChar() error!\"\n                + \" Please contact the authors.\";\n            scanner.useDelimiter(WHITESPACE_PATTERN);\n            return ch.charAt(0);\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'char' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n\n   /**\n     * Reads and returns the remainder of this input stream, as a string.\n     *\n     * @return the remainder of this input stream, as a string\n     */\n    public String readAll() {\n        if (!scanner.hasNextLine())\n            return \"\";\n\n        String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();\n        // not that important to reset delimeter, since now scanner is empty\n        scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway\n        return result;\n    }\n\n\n   /**\n     * Reads the next token from this input stream and returns it as a {@code String}.\n     *\n     * @return the next {@code String} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     */\n    public String readString() {\n        try {\n            return scanner.next();\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'String' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from this input stream, parses it as a {@code int},\n     * and returns the {@code int}.\n     *\n     * @return the next {@code int} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as an {@code int}\n     */\n    public int readInt() {\n        try {\n            return scanner.nextInt();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read an 'int' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read an 'int' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from this input stream, parses it as a {@code double},\n     * and returns the {@code double}.\n     *\n     * @return the next {@code double} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code double}\n     */\n    public double readDouble() {\n        try {\n            return scanner.nextDouble();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'double' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read a 'double' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from this input stream, parses it as a {@code float},\n     * and returns the {@code float}.\n     *\n     * @return the next {@code float} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code float}\n     */\n    public float readFloat() {\n        try {\n            return scanner.nextFloat();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'float' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read a 'float' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from this input stream, parses it as a {@code long},\n     * and returns the {@code long}.\n     *\n     * @return the next {@code long} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code long}\n     */\n    public long readLong() {\n        try {\n            return scanner.nextLong();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'long' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read a 'long' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from this input stream, parses it as a {@code short},\n     * and returns the {@code short}.\n     *\n     * @return the next {@code short} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code short}\n     */\n    public short readShort() {\n        try {\n            return scanner.nextShort();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'short' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read a 'short' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from this input stream, parses it as a {@code byte},\n     * and returns the {@code byte}.\n     * <p>\n     * To read binary data, use {@link BinaryIn}.\n     *\n     * @return the next {@code byte} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code byte}\n     */\n    public byte readByte() {\n        try {\n            return scanner.nextByte();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'byte' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read a 'byte' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n    /**\n     * Reads the next token from this input stream, parses it as a {@code boolean}\n     * (interpreting either {@code \"true\"} or {@code \"1\"} as {@code true},\n     * and either {@code \"false\"} or {@code \"0\"} as {@code false}).\n     *\n     * @return the next {@code boolean} in this input stream\n     * @throws NoSuchElementException if the input stream is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code boolean}\n     */\n    public boolean readBoolean() {\n        try {\n            String token = readString();\n            if (\"true\".equalsIgnoreCase(token))  return true;\n            if (\"false\".equalsIgnoreCase(token)) return false;\n            if (\"1\".equals(token))               return true;\n            if (\"0\".equals(token))               return false;\n            throw new InputMismatchException(\"attempts to read a 'boolean' value from the input stream, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'boolean' value from the input stream, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n    /**\n     * Reads all remaining tokens from this input stream and returns them as\n     * an array of strings.\n     *\n     * @return all remaining tokens in this input stream, as an array of strings\n     */\n    public String[] readAllStrings() {\n        // we could use readAll.trim().split(), but that's not consistent\n        // since trim() uses characters 0x00..0x20 as whitespace\n        String[] tokens = WHITESPACE_PATTERN.split(readAll());\n        if (tokens.length == 0 || tokens[0].length() > 0)\n            return tokens;\n        String[] decapitokens = new String[tokens.length-1];\n        for (int i = 0; i < tokens.length-1; i++)\n            decapitokens[i] = tokens[i+1];\n        return decapitokens;\n    }\n\n    /**\n     * Reads all remaining lines from this input stream and returns them as\n     * an array of strings.\n     *\n     * @return all remaining lines in this input stream, as an array of strings\n     */\n    public String[] readAllLines() {\n        ArrayList<String> lines = new ArrayList<String>();\n        while (hasNextLine()) {\n            lines.add(readLine());\n        }\n        return lines.toArray(new String[0]);\n    }\n\n\n    /**\n     * Reads all remaining tokens from this input stream, parses them as integers,\n     * and returns them as an array of integers.\n     *\n     * @return all remaining lines in this input stream, as an array of integers\n     */\n    public int[] readAllInts() {\n        String[] fields = readAllStrings();\n        int[] vals = new int[fields.length];\n        for (int i = 0; i < fields.length; i++)\n            vals[i] = Integer.parseInt(fields[i]);\n        return vals;\n    }\n\n    /**\n     * Reads all remaining tokens from this input stream, parses them as longs,\n     * and returns them as an array of longs.\n     *\n     * @return all remaining lines in this input stream, as an array of longs\n     */\n    public long[] readAllLongs() {\n        String[] fields = readAllStrings();\n        long[] vals = new long[fields.length];\n        for (int i = 0; i < fields.length; i++)\n            vals[i] = Long.parseLong(fields[i]);\n        return vals;\n    }\n\n    /**\n     * Reads all remaining tokens from this input stream, parses them as doubles,\n     * and returns them as an array of doubles.\n     *\n     * @return all remaining lines in this input stream, as an array of doubles\n     */\n    public double[] readAllDoubles() {\n        String[] fields = readAllStrings();\n        double[] vals = new double[fields.length];\n        for (int i = 0; i < fields.length; i++)\n            vals[i] = Double.parseDouble(fields[i]);\n        return vals;\n    }\n\n    ///// end: section (2 of 2) of code duplicated from In to StdIn */\n\n   /**\n     * Closes this input stream.\n     */\n    public void close() {\n        scanner.close();\n    }\n\n    /**\n     * Reads all integers from a file and returns them as\n     * an array of integers.\n     *\n     * @param      filename the name of the file\n     * @return     the integers in the file\n     * @deprecated Replaced by {@code new In(filename)}.{@link #readAllInts()}.\n     */\n    @Deprecated\n    public static int[] readInts(String filename) {\n        return new In(filename).readAllInts();\n    }\n\n   /**\n     * Reads all doubles from a file and returns them as\n     * an array of doubles.\n     *\n     * @param      filename the name of the file\n     * @return     the doubles in the file\n     * @deprecated Replaced by {@code new In(filename)}.{@link #readAllDoubles()}.\n     */\n    @Deprecated\n    public static double[] readDoubles(String filename) {\n        return new In(filename).readAllDoubles();\n    }\n\n   /**\n     * Reads all strings from a file and returns them as\n     * an array of strings.\n     *\n     * @param      filename the name of the file\n     * @return     the strings in the file\n     * @deprecated Replaced by {@code new In(filename)}.{@link #readAllStrings()}.\n     */\n    @Deprecated\n    public static String[] readStrings(String filename) {\n        return new In(filename).readAllStrings();\n    }\n\n    /**\n     * Reads all integers from standard input and returns them\n     * an array of integers.\n     *\n     * @return     the integers on standard input\n     * @deprecated Replaced by {@code new In()}.{@link #readAllInts()}.\n     */\n    @Deprecated\n    public static int[] readInts() {\n        return new In().readAllInts();\n    }\n\n   /**\n     * Reads all doubles from standard input and returns them as\n     * an array of doubles.\n     *\n     * @return     the doubles on standard input\n     * @deprecated Replaced by {@code new In()}.{@link #readAllDoubles()}.\n     */\n    @Deprecated\n    public static double[] readDoubles() {\n        return new In().readAllDoubles();\n    }\n\n   /**\n     * Reads all strings from standard input and returns them as\n     *  an array of strings.\n     *\n     * @return     the strings on standard input\n     * @deprecated Replaced by {@code new In()}.{@link #readAllStrings()}.\n     */\n    @Deprecated\n    public static String[] readStrings() {\n        return new In().readAllStrings();\n    }\n\n   /**\n     * Unit tests the {@code In} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in;\n        String urlName = \"https://introcs.cs.princeton.edu/java/stdlib/InTest.txt\";\n\n        // read from a URL\n        System.out.println(\"readAll() from URL \" + urlName);\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(urlName);\n            System.out.println(in.readAll());\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n        // read one line at a time from URL\n        System.out.println(\"readLine() from URL \" + urlName);\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(urlName);\n            while (!in.isEmpty()) {\n                String s = in.readLine();\n                System.out.println(s);\n            }\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n        // read one string at a time from URL\n        System.out.println(\"readString() from URL \" + urlName);\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(urlName);\n            while (!in.isEmpty()) {\n                String s = in.readString();\n                System.out.println(s);\n            }\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n\n        // read one line at a time from file in current directory\n        System.out.println(\"readLine() from current directory\");\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(\"./InTest.txt\");\n            while (!in.isEmpty()) {\n                String s = in.readLine();\n                System.out.println(s);\n            }\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n\n        // read one line at a time from file using relative path\n        System.out.println(\"readLine() from relative path\");\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(\"../stdlib/InTest.txt\");\n            while (!in.isEmpty()) {\n                String s = in.readLine();\n                System.out.println(s);\n            }\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n        // read one char at a time\n        System.out.println(\"readChar() from file\");\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(\"InTest.txt\");\n            while (!in.isEmpty()) {\n                char c = in.readChar();\n                System.out.print(c);\n            }\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n        System.out.println();\n\n        // read one line at a time from absolute OS X / Linux path\n        System.out.println(\"readLine() from absolute OS X / Linux path\");\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(\"/n/fs/introcs/www/java/stdlib/InTest.txt\");\n            while (!in.isEmpty()) {\n                String s = in.readLine();\n                System.out.println(s);\n            }\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n\n        // read one line at a time from absolute Windows path\n        System.out.println(\"readLine() from absolute Windows path\");\n        System.out.println(\"---------------------------------------------------------------------------\");\n        try {\n            in = new In(\"G:\\\\www\\\\introcs\\\\stdlib\\\\InTest.txt\");\n            while (!in.isEmpty()) {\n                String s = in.readLine();\n                System.out.println(s);\n            }\n            System.out.println();\n        }\n        catch (IllegalArgumentException e) {\n            System.out.println(e);\n        }\n        System.out.println();\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/IndexBinomialMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation: javac IndexBinomialMinPQ.java\n *  Execution:\n *  \n *  An index binomial heap.\n *  \n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The IndexBinomialMinPQ class represents an indexed priority queue of generic keys.\n *  It supports the usual insert and delete-the-minimum operations,\n *  along with delete and change-the-key methods. \n *  In order to let the client refer to keys on the priority queue,\n *  an integer between 0 and N-1 is associated with each key ; the client\n *  uses this integer to specify which key to delete or change.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  \n *  This implementation uses a binomial heap along with an array to associate\n *  keys with integers in the given range.\n *  The insert, delete-the-minimum, delete, change-key, decrease-key,\n *  increase-key and size operations take logarithmic time.\n *  The is-empty, min-index, min-key, and key-of operations take constant time.\n *  Construction takes time proportional to the specified capacity.\n *\n *  @author Tristan Claverie\n */\npublic class IndexBinomialMinPQ<Key> implements Iterable<Integer> {\n\tprivate Node<Key> head;    \t\t\t//Head of the list of roots\n\tprivate Node<Key>[] nodes; \t\t\t//Array of indexed Nodes of the heap\n\tprivate int n;\t\t\t   \t\t//Maximum size of the tree\n\tprivate final Comparator<Key> comparator;\t//Comparator over the keys\n\t\n\t//Represents a node of a Binomial Tree\n\tprivate class Node<Key> {\n\t\tKey key;\t\t\t\t//Key contained by the Node\n\t\tint order;\t\t\t\t//The order of the Binomial Tree rooted by this Node\n\t\tint index;\t\t\t\t//Index associated with the Key\n\t\tNode<Key> parent;\t\t\t//parent of this Node\n\t\tNode<Key> child, sibling;\t\t//child and sibling of this Node\n\t}\n\t\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0} to {@code N-1}\n     * Worst case is O(n)\n     * @param N number of keys in the priority queue, index from {@code 0} to {@code N-1}\n     * @throws java.lang.IllegalArgumentException if {@code N < 0}\n     */\n\tpublic IndexBinomialMinPQ(int N) {\n\t\tif (N < 0) throw new IllegalArgumentException(\"Cannot create a priority queue of negative size\");\n\t\tcomparator = new MyComparator();\n\t\tnodes = (Node<Key>[]) new Node[N];\n\t\tthis.n = N;\n\t}\n\t\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0} to {@code N-1}\n     * Worst case is O(n)\n     * @param N number of keys in the priority queue, index from {@code 0} to {@code N-1}\n     * @param comparator a Comparator over the keys\n     * @throws java.lang.IllegalArgumentException if {@code N < 0}\n     */\n\tpublic IndexBinomialMinPQ(int N, Comparator<Key> comparator) {\n\t\tif (N < 0) throw new IllegalArgumentException(\"Cannot create a priority queue of negative size\");\n\t\tthis.comparator = comparator;\n\t\tnodes = (Node<Key>[]) new Node[N];\n\t\tthis.n = N;\n\t}\n\n\t/**\n\t * Whether the priority queue is empty\n\t * Worst case is O(1)\n\t * @return true if the priority queue is empty, false if not\n\t */\n\tpublic boolean isEmpty() {\n\t\treturn head == null;\n\t}\n\n\t/**\n\t * Does the priority queue contains the index i ?\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @return true if i is on the priority queue, false if not\n\t */\n\tpublic boolean contains(int i) {\n\t\tif (i < 0 || i >= n) throw new IllegalArgumentException();\n\t\telse return nodes[i] != null;\n\t}\n\n\t/**\n\t * Number of elements currently on the priority queue\n\t * Worst case is O(log(n))\n\t * @return the number of elements on the priority queue\n\t */\n\tpublic int size() {\n\t\tint result = 0, tmp;\n\t\tfor (Node<Key> node = head; node != null; node = node.sibling) {\n\t\t\tif (node.order > 30) { throw new ArithmeticException(\"The number of elements cannot be evaluated, but the priority queue is still valid.\"); }\n\t\t\ttmp =  1 << node.order;\n\t\t\tresult |= tmp;\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Associates a key with an index\n\t * Worst case is O(log(n))\n\t * @param i an index\n\t * @param key a Key associated with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index is already in the queue\n\t */\n\tpublic void insert(int i, Key key) {\n\t\tif (i < 0 || i >= n) throw new IllegalArgumentException();\n\t\tif (contains(i)) throw new IllegalArgumentException(\"Specified index is already in the queue\");\n\t\tNode<Key> x = new Node<Key>();\n\t\tx.key = key;\n\t\tx.index = i;\n\t\tx.order = 0;\n\t\tnodes[i] = x;\n\t\tIndexBinomialMinPQ<Key> H = new IndexBinomialMinPQ<Key>();\n\t\tH.head = x;\n\t\thead = union(H).head;\n\t}\n\n\t/**\n\t * Gets the index associated with the minimum key\n\t * Worst case is O(log(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the index associated with the minimum key\n\t */\n\t\n\tpublic int minIndex() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\tNode<Key> min = head;\n\t\tNode<Key> current = head;\n\t\twhile (current.sibling != null) {\n\t\t\tmin = (greater(min.key, current.sibling.key)) ? current.sibling : min;\n\t\t\tcurrent = current.sibling;\n\t\t}\n\t\treturn min.index;\n\t}\n\n\t/**\n\t * Gets the minimum key currently in the queue\n\t * Worst case is O(log(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key currently in the priority queue\n\t */\n\t\n\tpublic Key minKey() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\tNode<Key> min = head;\n\t\tNode<Key> current = head;\n\t\twhile (current.sibling != null) {\n\t\t\tmin = (greater(min.key, current.sibling.key)) ? current.sibling : min;\n\t\t\tcurrent = current.sibling;\n\t\t}\n\t\treturn min.key;\n\t}\n\n\t/**\n\t * Deletes the minimum key\n\t * Worst case is O(log(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the index associated with the minimum key\n\t */\n\t\n\tpublic int delMin() {\n\t\tif(isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\tNode<Key> min = eraseMin();\n\t\tNode<Key> x = (min.child == null) ? min : min.child;\n\t\tif (min.child != null) {\n\t\t\tmin.child = null;\n\t\t\tNode<Key> prevx = null, nextx = x.sibling;\n\t\t\twhile (nextx != null) {\n\t\t\t\tx.parent = null; // for garbage collection\n\t\t\t\tx.sibling = prevx;\n\t\t\t\tprevx = x;\n\t\t\t\tx = nextx;nextx = nextx.sibling;\n\t\t\t}\n\t\t\tx.parent = null;\n\t\t\tx.sibling = prevx;\n\t\t\tIndexBinomialMinPQ<Key> H = new IndexBinomialMinPQ<Key>();\n\t\t\tH.head = x;\n\t\t\thead = union(H).head;\n\t\t}\n\t\treturn min.index;\n\t}\n\n\t/**\n\t * Gets the key associated with index i\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index is not in the queue\n\t * @return the key associated with index i\n\t */\n\t\n\tpublic Key keyOf(int i) {\n\t\tif (i < 0 || i >= n) throw new IllegalArgumentException();\n\t\tif (!contains(i)) throw new IllegalArgumentException(\"Specified index is not in the queue\");\n\t\treturn nodes[i].key;\n\t}\n\n\t/**\n\t * Changes the key associated with index i to the given key\n\t * Worst case is O(log(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index has no key associated with\n\t */\n\t\n\tpublic void changeKey(int i, Key key) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new IllegalArgumentException(\"Specified index is not in the queue\");\n\t\tif (greater(nodes[i].key, key))  decreaseKey(i, key);\n\t\telse \t\t\t\t\t\t\t increaseKey(i, key);\n\t}\n\n\t/**\n\t * Decreases the key associated with index i to the given key\n\t * Worst case is O(log(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t * @throws java.lang.IllegalArgumentException if the given key is greater than the current key\n\t */\n\t\n\tpublic void decreaseKey(int i, Key key) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (greater(key, nodes[i].key))  throw new IllegalArgumentException(\"Calling with this argument would not decrease the key\");\n\t\tNode<Key> x = nodes[i];\n\t\tx.key = key;\n\t\tswim(i);\n\t}\n\n\t/**\n\t * Increases the key associated with index i to the given key\n\t * Worst case is O(log(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t * @throws java.lang.IllegalArgumentException if the given key is lower than the current key\n\t */\n\t\n\tpublic void increaseKey(int i, Key key) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (greater(nodes[i].key, key))  throw new IllegalArgumentException(\"Calling with this argument would not increase the key\");\n\t\tdelete(i);\n\t\tinsert(i, key);\n\t}\n\n\t/**\n\t * Deletes the key associated the given index\n\t * Worst case is O(log(n))\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the given index has no key associated with\n\t */\n\t\n\tpublic void delete(int i) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\ttoTheRoot(i);\n\t\tNode<Key> x = erase(i);\n\t\tif (x.child != null) {\n\t\t\tNode<Key> y = x;\n\t\t\tx = x.child;\n\t\t\ty.child = null;\n\t\t\tNode<Key> prevx = null, nextx = x.sibling;\n\t\t\twhile (nextx != null) {\n\t\t\t\tx.parent = null;\n\t\t\t\tx.sibling = prevx;\n\t\t\t\tprevx = x;\n\t\t\t\tx = nextx; nextx = nextx.sibling;\n\t\t\t}\n\t\t\tx.parent = null;\n\t\t\tx.sibling = prevx;\n\t\t\tIndexBinomialMinPQ<Key> H = new IndexBinomialMinPQ<Key>();\n\t\t\tH.head = x;\n\t\t\thead = union(H).head;\n\t\t}\n\t}\n\t\n\t/*************************************************\n\t * General helper functions\n\t ************************************************/\n\t\n\t//Compares two keys\n\tprivate boolean greater(Key n, Key m) {\n\t\tif (n == null) return false;\n\t\tif (m == null) return true;\n\t\treturn comparator.compare(n, m) > 0;\n\t}\n\t\n\t//Exchanges the positions of two nodes\n\tprivate void exchange(Node<Key> x, Node<Key> y) {\n\t\tKey tempKey = x.key; x.key = y.key; y.key = tempKey;\n\t\tint tempInt = x.index; x.index = y.index; y.index = tempInt;\n\t\tnodes[x.index] = x;\n\t\tnodes[y.index] = y;\n\t}\n\t\n\t//Assuming root1 holds a greater key than root2, root2 becomes the new root\n\tprivate void link(Node<Key> root1, Node<Key> root2) {\n\t\troot1.sibling = root2.child;\n\t\troot1.parent = root2;\n\t\troot2.child = root1;\n\t\troot2.order++;\n\t}\n\t\n\t/*************************************************\n\t * Functions for moving upward\n\t ************************************************/\n\t\n\t//Moves a Node upward\n\tprivate void swim(int i) {\n\t\tNode<Key> x = nodes[i];\n\t\tNode<Key> parent = x.parent;\n\t\tif (parent != null && greater(parent.key, x.key)) {\n\t\t\texchange(x, parent);\n\t\t\tswim(i);\n\t\t}\n\t}\n\t\n\t//The key associated with i becomes the root of its Binomial Tree,\n\t//regardless of the order relation defined for the keys\n\tprivate void toTheRoot(int i) {\n\t\tNode<Key> x = nodes[i];\n\t\tNode<Key> parent = x.parent;\n\t\tif (parent != null) {\n\t\t\texchange(x, parent);\n\t\t\ttoTheRoot(i);\n\t\t}\n\t}\n\t\n\t/**************************************************\n\t * Functions for deleting a key\n\t *************************************************/\n\t\n\t//Assuming the key associated with i is in the root list,\n\t//deletes and return the node of index i\n\tprivate Node<Key> erase(int i) {\n\t\tNode<Key> reference = nodes[i];\n\t\tNode<Key> x = head;\n\t\tNode<Key> previous = null;\n\t\twhile (x != reference) {\n\t\t\tprevious = x;\n\t\t\tx = x.sibling;\n\t\t}\n\t\tprevious.sibling = x.sibling;\n\t\tif (x == head) head = head.sibling;\n\t\tnodes[i] = null;\n\t\treturn x;\n\t}\n\t\n\t//Deletes and return the node containing the minimum key\n\tprivate Node<Key> eraseMin() {\n\t\tNode<Key> min = head;\n\t\tNode<Key> previous = null;\n\t\tNode<Key> current = head;\n\t\twhile (current.sibling != null) {\n\t\t\tif (greater(min.key, current.sibling.key)) {\n\t\t\t\tprevious = current;\n\t\t\t\tmin = current.sibling;\n\t\t\t}\n\t\t\tcurrent = current.sibling;\n\t\t}\n\t\tprevious.sibling = min.sibling;\n\t\tif (min == head) head = min.sibling;\n\t\tnodes[min.index] = null;\n\t\treturn min;\n\t}\n\t\n\t/**************************************************\n\t * Functions for inserting a key in the heap\n\t *************************************************/\n\t\n\t//Merges two root lists into one, there can be up to 2 Binomial Trees of same order\n\tprivate Node<Key> merge(Node<Key> h, Node<Key> x, Node<Key> y) {\n\t\tif (x == null && y == null) return h;\n\t\telse if (x == null) \t\th.sibling = merge(y, null, y.sibling);\n\t\telse if (y == null) \t\th.sibling = merge(x, x.sibling, null);\n\t\telse if (x.order < y.order) h.sibling = merge(x, x.sibling, y);\n\t\telse \t\t\t\t\t\th.sibling = merge(y, x, y.sibling);\n\t\treturn h;\n\t}\n\t\n\t//Merges two Binomial Heaps together and returns the resulting Binomial Heap\n\t//It destroys the two Heaps in parameter, which should not be used any after.\n\t//To guarantee logarithmic time, this function assumes the arrays are up-to-date\n\tprivate IndexBinomialMinPQ<Key> union(IndexBinomialMinPQ<Key> heap) {\n\t\tthis.head = merge(new Node<Key>(), this.head, heap.head).sibling;\n\t\tNode<Key> x = this.head;\n\t\tNode<Key> prevx = null, nextx = x.sibling;\n\t\twhile (nextx != null) {\n\t\t\tif (x.order < nextx.order ||\n\t\t\t   (nextx.sibling != null && nextx.sibling.order == x.order)) {\n\t\t\t\tprevx = x; x = nextx;\n\t\t\t} else if (greater(nextx.key, x.key)) {\n\t\t\t\tx.sibling = nextx.sibling;\n\t\t\t\tlink(nextx, x);\n\t\t\t} else {\n\t\t\t\tif (prevx == null) { this.head = nextx; }\n\t\t\t\telse { prevx.sibling = nextx; }\n\t\t\t\tlink(x, nextx);\n\t\t\t\tx = nextx;\n\t\t\t}\n\t\t\tnextx = x.sibling;\n\t\t}\n\t\treturn this;\n\t}\n\t\n\t/******************************************************************\n\t * Constructor\n\t *****************************************************************/\n\t\n\t//Creates an empty heap\n\t//The comparator is instanciated because it needs to,\n\t//but won't be used by any heap created by this constructor\n\tprivate IndexBinomialMinPQ() { comparator = null; }\n\t\n\t/******************************************************************\n\t * Iterator\n\t *****************************************************************/\n\t\n\t/**\n\t * Gets an Iterator over the indexes in the priority queue in ascending order\n\t * The Iterator does not implement the remove() method\n\t * iterator() : Worst case is O(n)\n\t * next() : \tWorst case is O(log(n))\n\t * hasNext() : \tWorst case is O(1)\n\t * @return an Iterator over the indexes in the priority queue in ascending order\n\t */\n\t\n\tpublic Iterator<Integer> iterator() {\n\t\treturn new MyIterator();\n\t}\n\t\n\tprivate class MyIterator implements Iterator<Integer> {\n\t\tIndexBinomialMinPQ<Key> data;\n\t\t\n\t\t//Constructor clones recursively the elements in the queue\n\t\t//It takes linear time\n\t\tpublic MyIterator() {\n\t\t\tdata = new IndexBinomialMinPQ<Key>(n, comparator);\n\t\t\tdata.head = clone(head, null);\n\t\t}\n\t\t\n\t\tprivate Node<Key> clone(Node<Key> x, Node<Key> parent) {\n\t\t\tif (x == null) return null;\n\t\t\tNode<Key> node = new Node<Key>();\n\t\t\tnode.index = x.index;\n\t\t\tnode.key = x.key;\n\t\t\tdata.nodes[node.index] = node;\n\t\t\tnode.parent = parent;\n\t\t\tnode.sibling = clone(x.sibling, parent);\n\t\t\tnode.child = clone(x.child, node);\n\t\t\treturn node;\n\t\t}\n\t\t\n\t\tpublic boolean hasNext() {\n\t\t\treturn !data.isEmpty();\n\t\t}\n\t\t\n\t\tpublic Integer next() {\n                        if (!hasNext()) throw new NoSuchElementException();\n\t\t\treturn data.delMin();\n\t\t}\n\t\t\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Comparator\n\t **************************/\n\t\n\t//default Comparator\n\tprivate class MyComparator implements Comparator<Key> {\n\t\t@Override\n\t\tpublic int compare(Key key1, Key key2) {\n\t\t\treturn ((Comparable<Key>) key1).compareTo(key2);\n\t\t}\n\t}\n\t\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/IndexFibonacciMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation: javac IndexFibonacciMinPQ.java\n *  Execution:\n *  \n *  An index Fibonacci heap.\n *  \n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.HashMap;\nimport java.util.NoSuchElementException;\n\n/*\n *  The IndexFibonacciMinPQ class represents an indexed priority queue of generic keys.\n *  It supports the usual insert and delete-the-minimum operations,\n *  along with delete and change-the-key methods. \n *  In order to let the client refer to keys on the priority queue,\n *  an integer between 0 and N-1 is associated with each key ; the client\n *  uses this integer to specify which key to delete or change.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  \n *  This implementation uses a Fibonacci heap along with an array to associate\n *  keys with integers in the given range.\n *  The insert, size, is-empty, contains, minimum-index, minimum-key\n *  and key-of take constant time.\n *  The decrease-key operation takes amortized constant time.\n *  The delete, increase-key, delete-the-minimum, change-key take amortized logarithmic time.\n *  Construction takes time proportional to the specified capacity\n *\n *   WARNING: THIS VERSION HAS AT LEAST ONE BUG.\n *\n *  @author Tristan Claverie\n */\npublic class IndexFibonacciMinPQ<Key> implements Iterable<Integer> {\n\tprivate Node<Key>[] nodes;\t\t\t//Array of Nodes in the heap\n\tprivate Node<Key> head;\t\t\t\t//Head of the circular root list\n\tprivate Node<Key> min;\t\t\t\t//Minimum Node in the heap\n\tprivate int size;\t\t\t\t\t//Number of keys in the heap\n\tprivate int n;\t\t\t\t\t\t//Maximum number of elements in the heap\n\tprivate final Comparator<Key> comp; //Comparator over the keys\n\tprivate HashMap<Integer, Node<Key>> table = new HashMap<Integer, Node<Key>>(); //Used for the consolidate operation\n\t\n\t//Represents a Node of a tree\n\tprivate class Node<Key> {\n\t\tKey key;\t\t\t\t\t\t//Key of the Node\n\t\tint order;\t\t\t\t\t\t//The order of the tree rooted by this Node\n\t\tint index;\t\t\t\t\t\t//Index associated with the key\n\t\tNode<Key> prev, next;\t\t\t//siblings of the Node\n\t\tNode<Key> parent, child;\t\t//parent and child of this Node\n\t\tboolean mark;\t\t\t\t\t//Indicates if this Node already lost a child\n\t}\n\t\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0} and {@code N-1}\n     * Worst case is O(n)\n     * @param N number of keys in the priority queue, index from {@code 0} to {@code N-1}\n     * @throws java.lang.IllegalArgumentException if {@code N < 0}\n     */\n\tpublic IndexFibonacciMinPQ(int N) {\n\t\tif (N < 0) throw new IllegalArgumentException(\"Cannot create a priority queue of negative size\");\n\t\tn = N;\n\t\tnodes = (Node<Key>[]) new Node[n];\n\t\tcomp = new MyComparator();\n\t}\n\t\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0} and {@code N-1}\n     * Worst case is O(n)\n     * @param N number of keys in the priority queue, index from {@code 0} to {@code N-1}\n     * @param C a Comparator over the keys\n     * @throws java.lang.IllegalArgumentException if {@code N < 0}\n     */\n\tpublic IndexFibonacciMinPQ(Comparator<Key> C, int N) {\n\t\tif (N < 0) throw new IllegalArgumentException(\"Cannot create a priority queue of negative size\");\n\t\tn = N;\n\t\tnodes = (Node<Key>[]) new Node[n];\n\t\tcomp = C;\n\t}\n\n\t/**\n\t * Whether the priority queue is empty\n\t * Worst case is O(1)\n\t * @return true if the priority queue is empty, false if not\n\t */\n\t\n\tpublic boolean isEmpty() {\n\t\treturn size == 0;\n\t}\n\n\t/**\n\t * Does the priority queue contains the index i ?\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @return true if i is on the priority queue, false if not\n\t */\n\t\n\tpublic boolean contains(int i) {\n\t\tif (i < 0 || i >= n) throw new IllegalArgumentException();\n\t\telse \t\t\t\t return nodes[i] != null;\n\t}\n\n\t/**\n\t * Number of elements currently on the priority queue\n\t * Worst case is O(1)\n\t * @return the number of elements on the priority queue\n\t */\n\t\n\tpublic int size() {\n\t\treturn size;\n\t}\n\n\t/**\n\t * Associates a key with an index\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @param key a Key associated with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index is already in the queue\n\t */\n\t\n\tpublic void insert(int i, Key key) {\n\t\tif (i < 0 || i >= n) throw new IllegalArgumentException();\n\t\tif (contains(i)) throw new IllegalArgumentException(\"Specified index is already in the queue\");\n\t\tNode<Key> x = new Node<Key>();\n\t\tx.key = key;\n\t\tx.index = i;\n\t\tnodes[i] = x;\n\t\tsize++;\n\t\thead = insert(x, head);\n\t\tif (min == null) min = head;\n\t\telse \t\t\t min = (greater(min.key, key)) ? head : min;\n\t}\n\n\t/**\n\t * Get the index associated with the minimum key\n\t * Worst case is O(1)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the index associated with the minimum key\n\t */\n\t\n\tpublic int minIndex() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\treturn min.index;\n\t}\n\n\t/**\n\t * Get the minimum key currently in the queue\n\t * Worst case is O(1)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key currently in the priority queue\n\t */\n\t\n\tpublic Key minKey() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\treturn min.key;\n\t}\n\n\t/**\n\t * Delete the minimum key\n\t * Worst case is O(log(n)) (amortized)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the index associated with the minimum key\n\t */\n\t\n\tpublic int delMin() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\thead = cut(min, head);\n\t\tNode<Key> x = min.child;\n\t\tint index = min.index;\n\t\tmin.key = null;\t\t\t\t\t//For garbage collection\n\t\tif (x != null) {\n\t\t\tdo {\n\t\t\t\tx.parent = null;\n\t\t\t\tx = x.next;\n\t\t\t} while (x != min.child);\n\t\t\thead = meld(head, x);\n\t\t\tmin.child = null;\t\t\t//For garbage collection\n\t\t}\n\t\tsize--;\n\t\tif (!isEmpty()) consolidate();\n\t\telse \t\t\tmin = null;\n\t\tnodes[index] = null;\n\t\treturn index;\n\t}\n\n\t/**\n\t * Get the key associated with index i\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index is not in the queue\n\t * @return the key associated with index i\n\t */\n\t\n\tpublic Key keyOf(int i) {\n\t\tif (i < 0 || i >= n) throw new IllegalArgumentException();\n\t\tif (!contains(i)) throw new NoSuchElementException(\"Specified index is not in the queue\");\n\t\treturn nodes[i].key;\n\t}\n\n\t/**\n\t * Changes the key associated with index i to the given key\n\t * If the given key is greater, Worst case is O(log(n))\n\t * If the given key is lower, Worst case is O(1) (amortized)\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t */\n\t\n\tpublic void changeKey(int i, Key key) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (greater(key, nodes[i].key))  increaseKey(i, key);\n\t\telse \t\t\t\t\t\t\t decreaseKey(i, key);\n\t}\n\n\t/**\n\t * Decreases the key associated with index i to the given key\n\t * Worst case is O(1) (amortized).\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t * @throws java.lang.IllegalArgumentException if the given key is greater than the current key\n\t */\n\t\n\tpublic void decreaseKey(int i, Key key) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (greater(key, nodes[i].key))  throw new IllegalArgumentException(\"Calling with this argument would not decrease the key\");\n\t\tNode<Key> x = nodes[i];\n\t\tx.key = key;\n\t\tif (greater(min.key, key)) min = x;\n\t\tif (x.parent != null && greater(x.parent.key, key)) {\n\t\t\tcut(i);\n\t\t}\n\t}\n\n\t/**\n\t * Increases the key associated with index i to the given key\n\t * Worst case is O(log(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t * @throws java.lang.IllegalArgumentException if the given key is lower than the current key\n\t */\n\t\n\tpublic void increaseKey(int i, Key key) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (greater(nodes[i].key, key))  throw new IllegalArgumentException(\"Calling with this argument would not increase the key\");\n\t\tdelete(i);\n\t\tinsert(i, key);\n\t}\n\n\t/**\n\t * Deletes the key associated the given index\n\t * Worst case is O(log(n)) (amortized)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the given index has no key associated with\n\t */\n\t\n\tpublic void delete(int i) {\n\t\tif (i < 0 || i >= n) \t\tthrow new IllegalArgumentException();\n\t\tif (!contains(i))\t\t\tthrow new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tNode<Key> x = nodes[i];\n\t\tx.key = null;\t\t\t\t//For garbage collection\n\t\tif (x.parent != null) {\n\t\t\tcut(i);\n\t\t}\n\t\thead = cut(x, head);\n\t\tif (x.child != null) {\n\t\t\tNode<Key> child = x.child;\n\t\t\tx.child = null;\t\t\t//For garbage collection\n\t\t\tx = child;\n\t\t\tdo {\n\t\t\t\tchild.parent = null;\n\t\t\t\tchild = child.next;\n\t\t\t} while (child != x);\n\t\t\thead = meld(head, child);\n\t\t}\n\t\tif (!isEmpty()) consolidate();\n\t\telse \t\t\tmin = null;\n\t\tnodes[i] = null;\n\t\tsize--;\n\t}\n\t\n\t/*************************************\n\t * General helper functions\n\t ************************************/\n\t\n\t//Compares two keys\n\tprivate boolean greater(Key n, Key m) {\n\t\tif (n == null) return false;\n\t\tif (m == null) return true;\n\t\treturn comp.compare(n,  m) > 0;\n\t}\n\t\n\t//Assuming root1 holds a greater key than root2, root2 becomes the new root\n\tprivate void link(Node<Key> root1, Node<Key> root2) {\n\t\troot1.parent = root2;\n\t\troot2.child = insert(root1, root2.child);\n\t\troot2.order++;\n\t}\n\t\n\t/*************************************\n\t * Function for decreasing a key\n\t ************************************/\n\t\n\t//Removes a Node from its parent's child list and insert it in the root list\n\t//If the parent Node already lost a child, reshapes the heap accordingly\n\tprivate void cut(int i) {\n\t\tNode<Key> x = nodes[i];\n\t\tNode<Key> parent = x.parent;\n\t\tparent.child = cut(x, parent.child);\n\t\tx.parent = null;\n\t\tparent.order--;\n\t\thead = insert(x, head);\n\t\tparent.mark = !parent.mark;\n\t\tif (!parent.mark && parent.parent != null) {\n\t\t\tcut(parent.index);}\n\t}\n\t\n\t/*************************************\n\t * Function for consolidating all trees in the root list\n\t ************************************/\n\t\n\t//Coalesces the roots, thus reshapes the heap\n\t//Caching a HashMap improves greatly performances\n\tprivate void consolidate() {\n\t\ttable.clear();\n\t\tNode<Key> x = head;\n\t\tint maxOrder = 0;\n\t\tmin = head;\n\t\tNode<Key> y = null, z = null;\n\t\tdo {\n\t\t\ty = x;\n\t\t\tx = x.next;\n\t\t\tz = table.get(y.order);\n\t\t\twhile (z != null) {\n\t\t\t\ttable.remove(y.order);\n\t\t\t\tif (greater(y.key, z.key)) {\n\t\t\t\t\tlink(y, z);\n\t\t\t\t\ty = z;\n\t\t\t\t} else {\n\t\t\t\t\tlink(z, y);\n\t\t\t\t}\n\t\t\t\tz = table.get(y.order);\n\t\t\t}\n\t\t\ttable.put(y.order, y);\n\t\t\tif (y.order > maxOrder) maxOrder = y.order;\n\t\t} while (x != head);\n\t\thead = null;\n\t\tfor (Node<Key> n : table.values()) {\n\t\t\tmin = greater(min.key, n.key) ? n : min;\n\t\t\thead = insert(n, head);\n\t\t}\n\t}\n\t\n\t/*************************************\n\t * General helper functions for manipulating circular lists\n\t ************************************/\n\t\n\t//Inserts a Node in a circular list containing head, returns a new head\n\tprivate Node<Key> insert(Node<Key> x, Node<Key> head) {\n\t\tif (head == null) {\n\t\t\tx.prev = x;\n\t\t\tx.next = x;\n\t\t} else {\n\t\t\thead.prev.next = x;\n\t\t\tx.next = head;\n\t\t\tx.prev = head.prev;\n\t\t\thead.prev = x;\n\t\t}\n\t\treturn x;\n\t}\n\t\n\t//Removes a tree from the list defined by the head pointer\n\tprivate Node<Key> cut(Node<Key> x, Node<Key> head) {\n\t\tif (x.next == x) {\n\t\t\tx.next = null;\n\t\t\tx.prev = null;\n\t\t\treturn null;\n\t\t} else {\n\t\t\tx.next.prev = x.prev;\n\t\t\tx.prev.next = x.next;\n\t\t\tNode<Key> res = x.next;\n\t\t\tx.next = null;\n\t\t\tx.prev = null;\n\t\t\tif (head == x)  return res;\n\t\t\telse \t\t\treturn head;\n\t\t}\n\t}\n\t\n\t//Merges two lists together.\n\tprivate Node<Key> meld(Node<Key> x, Node<Key> y) {\n\t\tif (x == null) return y;\n\t\tif (y == null) return x;\n\t\tx.prev.next = y.next;\n\t\ty.next.prev = x.prev;\n\t\tx.prev = y;\n\t\ty.next = x;\n\t\treturn x;\n\t}\n\t\n\t/*************************************\n\t * Iterator\n\t ************************************/\n\t\n\t/**\n\t * Get an Iterator over the indexes in the priority queue in ascending order\n\t * The Iterator does not implement the remove() method\n\t * iterator() : Worst case is O(n)\n\t * next() : \tWorst case is O(log(n)) (amortized)\n\t * hasNext() : \tWorst case is O(1)\n\t * @return an Iterator over the indexes in the priority queue in ascending order\n\t */\n\t\n\tpublic Iterator<Integer> iterator() {\n\t\treturn new MyIterator();\n\t}\n\t\n\tprivate class MyIterator implements Iterator<Integer> {\n\t\tprivate IndexFibonacciMinPQ<Key> copy;\n\t\t\n\t\t\n\t\t//Constructor takes linear time\n\t\tpublic MyIterator() {\n\t\t\tcopy = new IndexFibonacciMinPQ<Key>(comp, n);\n\t\t\tfor (Node<Key> x : nodes) {\n\t\t\t\tif (x != null) copy.insert(x.index, x.key);\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\t\n\t\tpublic boolean hasNext() {\n\t\t\treturn !copy.isEmpty();\n\t\t}\n\t\t\n\t\t//Takes amortized logarithmic time\n\t\tpublic Integer next() {\n\t\t\tif (!hasNext()) throw new NoSuchElementException();\n\t\t\treturn copy.delMin();\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Comparator\n\t **************************/\n\t\n\t//default Comparator\n\tprivate class MyComparator implements Comparator<Key> {\n\t\t@Override\n\t\tpublic int compare(Key key1, Key key2) {\n\t\t\treturn ((Comparable<Key>) key1).compareTo(key2);\n\t\t}\n\t}\n\t\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/IndexMaxPQ.java",
    "content": "/******************************************************************************\n *  Compilation:  javac IndexMaxPQ.java\n *  Execution:    java IndexMaxPQ\n *  Dependencies: StdOut.java\n *\n *  Maximum-oriented indexed PQ implementation using a binary heap.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code IndexMaxPQ} class represents an indexed priority queue of generic keys.\n *  It supports the usual <em>insert</em> and <em>delete-the-maximum</em>\n *  operations, along with <em>delete</em> and <em>change-the-key</em>\n *  methods. In order to let the client refer to items on the priority queue,\n *  an integer between {@code 0} and {@code maxN - 1}\n *  is associated with each key—the client\n *  uses this integer to specify which key to delete or change.\n *  It also supports methods for peeking at a maximum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  <p>\n *  This implementation uses a <em>binary heap</em> along with an\n *  array to associate keys with integers in the given range.\n *  The <em>insert</em>, <em>delete-the-maximum</em>, <em>delete</em>,\n *  <em>change-key</em>, <em>decrease-key</em>, and <em>increase-key</em>\n *  operations take &Theta;(log <em>n</em>) time in the worst case,\n *  where <em>n</em> is the number of elements in the priority queue.\n *  Construction takes time proportional to the specified capacity.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Key> the generic type of key on this priority queue\n */\npublic class IndexMaxPQ<Key extends Comparable<Key>> implements Iterable<Integer> {\n    private int maxN;        // maximum number of elements on PQ\n    private int n;           // number of elements on PQ\n    private int[] pq;        // binary heap using 1-based indexing\n    private int[] qp;        // inverse of pq - qp[pq[i]] = pq[qp[i]] = i\n    private Key[] keys;      // keys[i] = priority of i\n\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0}\n     * and {@code maxN - 1}.\n     *\n     * @param  maxN the keys on this priority queue are index from {@code 0} to {@code maxN - 1}\n     * @throws IllegalArgumentException if {@code maxN < 0}\n     */\n    public IndexMaxPQ(int maxN) {\n        if (maxN < 0) throw new IllegalArgumentException();\n        this.maxN = maxN;\n        n = 0;\n        keys = (Key[]) new Comparable[maxN + 1];    // make this of length maxN??\n        pq   = new int[maxN + 1];\n        qp   = new int[maxN + 1];                   // make this of length maxN??\n        for (int i = 0; i <= maxN; i++)\n            qp[i] = -1;\n    }\n\n    /**\n     * Returns true if this priority queue is empty.\n     *\n     * @return {@code true} if this priority queue is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Is {@code i} an index on this priority queue?\n     *\n     * @param  i an index\n     * @return {@code true} if {@code i} is an index on this priority queue;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     */\n    public boolean contains(int i) {\n        validateIndex(i);\n        return qp[i] != -1;\n    }\n\n    /**\n     * Returns the number of keys on this priority queue.\n     *\n     * @return the number of keys on this priority queue\n     */\n    public int size() {\n        return n;\n    }\n\n   /**\n     * Associate key with index i.\n     *\n     * @param  i an index\n     * @param  key the key to associate with index {@code i}\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws IllegalArgumentException if there already is an item\n     *         associated with index {@code i}\n     */\n    public void insert(int i, Key key) {\n        validateIndex(i);\n        if (contains(i)) throw new IllegalArgumentException(\"index is already in the priority queue\");\n        n++;\n        qp[i] = n;\n        pq[n] = i;\n        keys[i] = key;\n        swim(n);\n    }\n\n    /**\n     * Returns an index associated with a maximum key.\n     *\n     * @return an index associated with a maximum key\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public int maxIndex() {\n        if (n == 0) throw new NoSuchElementException(\"Priority queue underflow\");\n        return pq[1];\n    }\n\n    /**\n     * Returns a maximum key.\n     *\n     * @return a maximum key\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public Key maxKey() {\n        if (n == 0) throw new NoSuchElementException(\"Priority queue underflow\");\n        return keys[pq[1]];\n    }\n\n    /**\n     * Removes a maximum key and returns its associated index.\n     *\n     * @return an index associated with a maximum key\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public int delMax() {\n        if (n == 0) throw new NoSuchElementException(\"Priority queue underflow\");\n        int max = pq[1];\n        exch(1, n--);\n        sink(1);\n\n        assert pq[n+1] == max;\n        qp[max] = -1;        // delete\n        keys[max] = null;    // to help with garbage collection\n        pq[n+1] = -1;        // not needed\n        return max;\n    }\n\n    /**\n     * Returns the key associated with index {@code i}.\n     *\n     * @param  i the index of the key to return\n     * @return the key associated with index {@code i}\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public Key keyOf(int i) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        else return keys[i];\n    }\n\n    /**\n     * Change the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to change\n     * @param  key change the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     */\n    public void changeKey(int i, Key key) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        keys[i] = key;\n        swim(qp[i]);\n        sink(qp[i]);\n    }\n\n   /**\n     * Change the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to change\n     * @param  key change the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @deprecated Replaced by {@code changeKey(int, Key)}.\n     */\n    @Deprecated\n    public void change(int i, Key key) {\n        validateIndex(i);\n        changeKey(i, key);\n    }\n\n    /**\n     * Increase the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to increase\n     * @param  key increase the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws IllegalArgumentException if {@code key <= keyOf(i)}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void increaseKey(int i, Key key) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        if (keys[i].compareTo(key) == 0)\n            throw new IllegalArgumentException(\"Calling increaseKey() with a key equal to the key in the priority queue\");\n        if (keys[i].compareTo(key) > 0)\n            throw new IllegalArgumentException(\"Calling increaseKey() with a key that is strictly less than the key in the priority queue\");\n\n        keys[i] = key;\n        swim(qp[i]);\n    }\n\n    /**\n     * Decrease the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to decrease\n     * @param  key decrease the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws IllegalArgumentException if {@code key >= keyOf(i)}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void decreaseKey(int i, Key key) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        if (keys[i].compareTo(key) == 0)\n            throw new IllegalArgumentException(\"Calling decreaseKey() with a key equal to the key in the priority queue\");\n        if (keys[i].compareTo(key) < 0)\n            throw new IllegalArgumentException(\"Calling decreaseKey() with a key that is strictly greater than the key in the priority queue\");\n        keys[i] = key;\n        sink(qp[i]);\n    }\n\n    /**\n     * Remove the key on the priority queue associated with index {@code i}.\n     *\n     * @param  i the index of the key to remove\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void delete(int i) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        int index = qp[i];\n        exch(index, n--);\n        swim(index);\n        sink(index);\n        keys[i] = null;\n        qp[i] = -1;\n    }\n\n    // throw an IllegalArgumentException if i is an invalid index\n    private void validateIndex(int i) {\n        if (i < 0) throw new IllegalArgumentException(\"index is negative: \" + i);\n        if (i >= maxN) throw new IllegalArgumentException(\"index >= capacity: \" + i);\n    }\n\n   /***************************************************************************\n    * General helper functions.\n    ***************************************************************************/\n    private boolean less(int i, int j) {\n        return keys[pq[i]].compareTo(keys[pq[j]]) < 0;\n    }\n\n    private void exch(int i, int j) {\n        int swap = pq[i];\n        pq[i] = pq[j];\n        pq[j] = swap;\n        qp[pq[i]] = i;\n        qp[pq[j]] = j;\n    }\n\n\n   /***************************************************************************\n    * Heap helper functions.\n    ***************************************************************************/\n    private void swim(int k) {\n        while (k > 1 && less(k/2, k)) {\n            exch(k, k/2);\n            k = k/2;\n        }\n    }\n\n    private void sink(int k) {\n        while (2*k <= n) {\n            int j = 2*k;\n            if (j < n && less(j, j+1)) j++;\n            if (!less(k, j)) break;\n            exch(k, j);\n            k = j;\n        }\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the keys on the\n     * priority queue in descending order.\n     * The iterator doesn't implement {@code remove()} since it's optional.\n     *\n     * @return an iterator that iterates over the keys in descending order\n     */\n    public Iterator<Integer> iterator() {\n        return new HeapIterator();\n    }\n\n    private class HeapIterator implements Iterator<Integer> {\n        // create a new pq\n        private IndexMaxPQ<Key> copy;\n\n        // add all elements to copy of heap\n        // takes linear time since already in heap order so no keys move\n        public HeapIterator() {\n            copy = new IndexMaxPQ<Key>(pq.length - 1);\n            for (int i = 1; i <= n; i++)\n                copy.insert(pq[i], keys[pq[i]]);\n        }\n\n        public boolean hasNext()  { return !copy.isEmpty();                     }\n        public void remove()      { throw new UnsupportedOperationException();  }\n\n        public Integer next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            return copy.delMax();\n        }\n    }\n\n    /**\n     * Unit tests the {@code IndexMaxPQ} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        // insert a bunch of strings\n        String[] strings = { \"it\", \"was\", \"the\", \"best\", \"of\", \"times\", \"it\", \"was\", \"the\", \"worst\" };\n\n        IndexMaxPQ<String> pq = new IndexMaxPQ<String>(strings.length);\n        for (int i = 0; i < strings.length; i++) {\n            pq.insert(i, strings[i]);\n        }\n\n        // print each key using the iterator\n        for (int i : pq) {\n            StdOut.println(i + \" \" + strings[i]);\n        }\n\n        StdOut.println();\n\n        // increase or decrease the key\n        for (int i = 0; i < strings.length; i++) {\n            if (StdRandom.bernoulli(0.5))\n                pq.increaseKey(i, strings[i] + strings[i]);\n            else\n                pq.decreaseKey(i, strings[i].substring(0, 1));\n        }\n\n        // delete and print each key\n        while (!pq.isEmpty()) {\n            String key = pq.maxKey();\n            int i = pq.delMax();\n            StdOut.println(i + \" \" + key);\n        }\n        StdOut.println();\n\n        // reinsert the same strings\n        for (int i = 0; i < strings.length; i++) {\n            pq.insert(i, strings[i]);\n        }\n\n        // delete them in random order\n        int[] perm = new int[strings.length];\n        for (int i = 0; i < strings.length; i++)\n            perm[i] = i;\n        StdRandom.shuffle(perm);\n        for (int i = 0; i < perm.length; i++) {\n            String key = pq.keyOf(perm[i]);\n            pq.delete(perm[i]);\n            StdOut.println(perm[i] + \" \" + key);\n        }\n\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/IndexMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation:  javac IndexMinPQ.java\n *  Execution:    java IndexMinPQ\n *  Dependencies: StdOut.java\n *\n *  Minimum-oriented indexed PQ implementation using a binary heap.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code IndexMinPQ} class represents an indexed priority queue of generic keys.\n *  It supports the usual <em>insert</em> and <em>delete-the-minimum</em>\n *  operations, along with <em>delete</em> and <em>change-the-key</em>\n *  methods. In order to let the client refer to keys on the priority queue,\n *  an integer between {@code 0} and {@code maxN - 1}\n *  is associated with each key—the client uses this integer to specify\n *  which key to delete or change.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  <p>\n *  This implementation uses a binary heap along with an array to associate\n *  keys with integers in the given range.\n *  The <em>insert</em>, <em>delete-the-minimum</em>, <em>delete</em>,\n *  <em>change-key</em>, <em>decrease-key</em>, and <em>increase-key</em>\n *  operations take &Theta;(log <em>n</em>) time in the worst case,\n *  where <em>n</em> is the number of elements in the priority queue.\n *  Construction takes time proportional to the specified capacity.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Key> the generic type of key on this priority queue\n */\npublic class IndexMinPQ<Key extends Comparable<Key>> implements Iterable<Integer> {\n    private int maxN;        // maximum number of elements on PQ\n    private int n;           // number of elements on PQ\n    private int[] pq;        // binary heap using 1-based indexing\n    private int[] qp;        // inverse of pq - qp[pq[i]] = pq[qp[i]] = i\n    private Key[] keys;      // keys[i] = priority of i\n\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0}\n     * and {@code maxN - 1}.\n     * @param  maxN the keys on this priority queue are index from {@code 0}\n     *         {@code maxN - 1}\n     * @throws IllegalArgumentException if {@code maxN < 0}\n     */\n    public IndexMinPQ(int maxN) {\n        if (maxN < 0) throw new IllegalArgumentException();\n        this.maxN = maxN;\n        n = 0;\n        keys = (Key[]) new Comparable[maxN + 1];    // make this of length maxN??\n        pq   = new int[maxN + 1];\n        qp   = new int[maxN + 1];                   // make this of length maxN??\n        for (int i = 0; i <= maxN; i++)\n            qp[i] = -1;\n    }\n\n    /**\n     * Returns true if this priority queue is empty.\n     *\n     * @return {@code true} if this priority queue is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Is {@code i} an index on this priority queue?\n     *\n     * @param  i an index\n     * @return {@code true} if {@code i} is an index on this priority queue;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     */\n    public boolean contains(int i) {\n        validateIndex(i);\n        return qp[i] != -1;\n    }\n\n    /**\n     * Returns the number of keys on this priority queue.\n     *\n     * @return the number of keys on this priority queue\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Associates key with index {@code i}.\n     *\n     * @param  i an index\n     * @param  key the key to associate with index {@code i}\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws IllegalArgumentException if there already is an item associated\n     *         with index {@code i}\n     */\n    public void insert(int i, Key key) {\n        validateIndex(i);\n        if (contains(i)) throw new IllegalArgumentException(\"index is already in the priority queue\");\n        n++;\n        qp[i] = n;\n        pq[n] = i;\n        keys[i] = key;\n        swim(n);\n    }\n\n    /**\n     * Returns an index associated with a minimum key.\n     *\n     * @return an index associated with a minimum key\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public int minIndex() {\n        if (n == 0) throw new NoSuchElementException(\"Priority queue underflow\");\n        return pq[1];\n    }\n\n    /**\n     * Returns a minimum key.\n     *\n     * @return a minimum key\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public Key minKey() {\n        if (n == 0) throw new NoSuchElementException(\"Priority queue underflow\");\n        return keys[pq[1]];\n    }\n\n    /**\n     * Removes a minimum key and returns its associated index.\n     * @return an index associated with a minimum key\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public int delMin() {\n        if (n == 0) throw new NoSuchElementException(\"Priority queue underflow\");\n        int min = pq[1];\n        exch(1, n--);\n        sink(1);\n        assert min == pq[n+1];\n        qp[min] = -1;        // delete\n        keys[min] = null;    // to help with garbage collection\n        pq[n+1] = -1;        // not needed\n        return min;\n    }\n\n    /**\n     * Returns the key associated with index {@code i}.\n     *\n     * @param  i the index of the key to return\n     * @return the key associated with index {@code i}\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public Key keyOf(int i) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        else return keys[i];\n    }\n\n    /**\n     * Change the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to change\n     * @param  key change the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void changeKey(int i, Key key) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        keys[i] = key;\n        swim(qp[i]);\n        sink(qp[i]);\n    }\n\n    /**\n     * Change the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to change\n     * @param  key change the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @deprecated Replaced by {@code changeKey(int, Key)}.\n     */\n    @Deprecated\n    public void change(int i, Key key) {\n        changeKey(i, key);\n    }\n\n    /**\n     * Decrease the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to decrease\n     * @param  key decrease the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws IllegalArgumentException if {@code key >= keyOf(i)}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void decreaseKey(int i, Key key) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        if (keys[i].compareTo(key) == 0)\n            throw new IllegalArgumentException(\"Calling decreaseKey() with a key equal to the key in the priority queue\");\n        if (keys[i].compareTo(key) < 0)\n            throw new IllegalArgumentException(\"Calling decreaseKey() with a key strictly greater than the key in the priority queue\");\n        keys[i] = key;\n        swim(qp[i]);\n    }\n\n    /**\n     * Increase the key associated with index {@code i} to the specified value.\n     *\n     * @param  i the index of the key to increase\n     * @param  key increase the key associated with index {@code i} to this key\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws IllegalArgumentException if {@code key <= keyOf(i)}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void increaseKey(int i, Key key) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        if (keys[i].compareTo(key) == 0)\n            throw new IllegalArgumentException(\"Calling increaseKey() with a key equal to the key in the priority queue\");\n        if (keys[i].compareTo(key) > 0)\n            throw new IllegalArgumentException(\"Calling increaseKey() with a key strictly less than the key in the priority queue\");\n        keys[i] = key;\n        sink(qp[i]);\n    }\n\n    /**\n     * Remove the key associated with index {@code i}.\n     *\n     * @param  i the index of the key to remove\n     * @throws IllegalArgumentException unless {@code 0 <= i < maxN}\n     * @throws NoSuchElementException no key is associated with index {@code i}\n     */\n    public void delete(int i) {\n        validateIndex(i);\n        if (!contains(i)) throw new NoSuchElementException(\"index is not in the priority queue\");\n        int index = qp[i];\n        exch(index, n--);\n        swim(index);\n        sink(index);\n        keys[i] = null;\n        qp[i] = -1;\n    }\n\n    // throw an IllegalArgumentException if i is an invalid index\n    private void validateIndex(int i) {\n        if (i < 0) throw new IllegalArgumentException(\"index is negative: \" + i);\n        if (i >= maxN) throw new IllegalArgumentException(\"index >= capacity: \" + i);\n    }\n\n   /***************************************************************************\n    * General helper functions.\n    ***************************************************************************/\n    private boolean greater(int i, int j) {\n        return keys[pq[i]].compareTo(keys[pq[j]]) > 0;\n    }\n\n    private void exch(int i, int j) {\n        int swap = pq[i];\n        pq[i] = pq[j];\n        pq[j] = swap;\n        qp[pq[i]] = i;\n        qp[pq[j]] = j;\n    }\n\n\n   /***************************************************************************\n    * Heap helper functions.\n    ***************************************************************************/\n    private void swim(int k) {\n        while (k > 1 && greater(k/2, k)) {\n            exch(k, k/2);\n            k = k/2;\n        }\n    }\n\n    private void sink(int k) {\n        while (2*k <= n) {\n            int j = 2*k;\n            if (j < n && greater(j, j+1)) j++;\n            if (!greater(k, j)) break;\n            exch(k, j);\n            k = j;\n        }\n    }\n\n\n   /***************************************************************************\n    * Iterators.\n    ***************************************************************************/\n\n    /**\n     * Returns an iterator that iterates over the keys on the\n     * priority queue in ascending order.\n     * The iterator doesn't implement {@code remove()} since it's optional.\n     *\n     * @return an iterator that iterates over the keys in ascending order\n     */\n    public Iterator<Integer> iterator() { return new HeapIterator(); }\n\n    private class HeapIterator implements Iterator<Integer> {\n        // create a new pq\n        private IndexMinPQ<Key> copy;\n\n        // add all elements to copy of heap\n        // takes linear time since already in heap order so no keys move\n        public HeapIterator() {\n            copy = new IndexMinPQ<Key>(pq.length - 1);\n            for (int i = 1; i <= n; i++)\n                copy.insert(pq[i], keys[pq[i]]);\n        }\n\n        public boolean hasNext()  { return !copy.isEmpty();                     }\n        public void remove()      { throw new UnsupportedOperationException();  }\n\n        public Integer next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            return copy.delMin();\n        }\n    }\n\n\n    /**\n     * Unit tests the {@code IndexMinPQ} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        // insert a bunch of strings\n        String[] strings = { \"it\", \"was\", \"the\", \"best\", \"of\", \"times\", \"it\", \"was\", \"the\", \"worst\" };\n\n        IndexMinPQ<String> pq = new IndexMinPQ<String>(strings.length);\n        for (int i = 0; i < strings.length; i++) {\n            pq.insert(i, strings[i]);\n        }\n\n        // delete and print each key\n        while (!pq.isEmpty()) {\n            int i = pq.delMin();\n            StdOut.println(i + \" \" + strings[i]);\n        }\n        StdOut.println();\n\n        // reinsert the same strings\n        for (int i = 0; i < strings.length; i++) {\n            pq.insert(i, strings[i]);\n        }\n\n        // print each key using the iterator\n        for (int i : pq) {\n            StdOut.println(i + \" \" + strings[i]);\n        }\n        while (!pq.isEmpty()) {\n            pq.delMin();\n        }\n\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/IndexMultiwayMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation: javac IndexMultiwayMinPQ.java\n *  Execution:\n *\n *  An inde  multiway heap.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The IndexMultiwayMinPQ class represents an indexed priority queue of generic keys.\n *  It supports the usual insert and delete-the-minimum operations,\n *  along with delete and change-the-key methods. \n *  In order to let the client refer to keys on the priority queue,\n *  an integer between 0 and N-1 is associated with each key ; the client\n *  uses this integer to specify which key to delete or change.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  \n *  This implementation uses a multiway heap along with an array to associate\n *  keys with integers in the given range.\n *  For simplified notations, logarithm in base d will be referred as log-d\n *  The delete-the-minimum, delete, change-key and increase-key operations\n *  take time proportional to d*log-d(n)\n *  The insert and decrease-key take time proportional to log-d(n)\n *  The is-empty, min-index, min-key, size, contains and key-of operations take constant time.\n *  Construction takes time proportional to the specified capacity.\n *  \n *  The arrays used in this structure have the first d indices empty,\n *  it apparently helps with caching effects.\n *\n *  @author Tristan Claverie\n */\npublic class IndexMultiwayMinPQ<Key> implements Iterable<Integer> {\n\tprivate final int d;\t\t\t\t//Dimension of the heap\n\tprivate int n;\t\t\t\t\t\t//Number of keys currently in the queue\n\tprivate int nmax;\t\t\t\t\t//Maximum number of items in the queue\n\tprivate int[] pq;\t\t\t\t\t//Multiway heap\n\tprivate int[] qp;\t\t\t\t\t//Inverse of pq : qp[pq[i]] = pq[qp[i]] = i\n\tprivate Key[] keys;\t\t\t\t\t//keys[i] = priority of i\n\tprivate final Comparator<Key> comp; //Comparator over the keys\n\t\n\t\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0} to {@code N-1}\n     * Worst case is O(n)\n     * @param N number of keys in the priority queue, index from {@code 0} to {@code N-1}\n     * @param D dimension of the heap\n     * @throws java.lang.IllegalArgumentException if {@code N < 0}\n     * @throws java.lang.IllegalArgumentException if {@code D < 2}\n     */\n\tpublic IndexMultiwayMinPQ(int N, int D) {\n\t\tif (N < 0) throw new IllegalArgumentException(\"Maximum number of elements cannot be negative\");\n\t\tif (D < 2) throw new IllegalArgumentException(\"Dimension should be 2 or over\");\n\t\tthis.d = D;\n\t\tnmax = N;\n\t\tpq = new int[nmax+D];\n\t\tqp = new int[nmax+D];\n\t\tkeys = (Key[]) new Comparable[nmax+D];\n\t\tfor (int i = 0; i < nmax+D; qp[i++] = -1);\n\t\tcomp = new MyComparator();\n\t}\n\t\n    /**\n     * Initializes an empty indexed priority queue with indices between {@code 0} to {@code N-1}\n     * Worst case is O(n)\n     * @param N number of keys in the priority queue, index from {@code 0} to {@code N-1}\n     * @param D dimension of the heap\n     * @param C a Comparator over the keys\n     * @throws java.lang.IllegalArgumentException if {@code N < 0}\n     * @throws java.lang.IllegalArgumentException if {@code D < 2}\n     */\n\tpublic IndexMultiwayMinPQ(int N, Comparator<Key> C, int D) {\n\t\tif (N < 0) throw new IllegalArgumentException(\"Maximum number of elements cannot be negative\");\n\t\tif (D < 2) throw new IllegalArgumentException(\"Dimension should be 2 or over\");\n\t\tthis.d = D;\n\t\tnmax = N;\n\t\tpq = new int[nmax+D];\n\t\tqp = new int[nmax+D];\n\t\tkeys = (Key[]) new Comparable[nmax+D];\n\t\tfor (int i = 0; i < nmax+D; qp[i++] = -1);\n\t\tcomp = C;\n\t}\n\n\t/**\n\t * Whether the priority queue is empty\n\t * Worst case is O(1)\n\t * @return true if the priority queue is empty, false if not\n\t */\n\tpublic boolean isEmpty() {\n\t\treturn n == 0;\n\t}\n\n\t/**\n\t * Does the priority queue contains the index i ?\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @return true if i is on the priority queue, false if not\n\t */\n\tpublic boolean contains(int i) {\n\t\tif (i < 0 ||i >= nmax) throw new IllegalArgumentException();\n\t\treturn qp[i+d] != -1;\n\t}\n\n\t/**\n\t * Number of elements currently on the priority queue\n\t * Worst case is O(1)\n\t * @return the number of elements on the priority queue\n\t */\n\tpublic int size() {\n\t\treturn n;\n\t}\n\n\t/**\n\t * Associates a key with an index\n\t * Worst case is O(log-d(n))\n\t * @param i an index\n\t * @param key a Key associated with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index is already in the queue\n\t */\n\tpublic void insert(int i, Key key) {\n\t\tif (i < 0 || i >= nmax) throw new IllegalArgumentException();\n\t\tif (contains(i)) throw new IllegalArgumentException(\"Index already there\");\n\t\tkeys[i+d] = key;\n\t\tpq[n+d] = i;\n\t\tqp[i+d] = n;\n\t\tswim(n++);\n\t}\n\n\t/**\n\t * Gets the index associated with the minimum key\n\t * Worst case is O(1)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the index associated with the minimum key\n\t */\n\tpublic int minIndex() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\treturn pq[d];\n\t}\n\n\t/**\n\t * Gets the minimum key currently in the queue\n\t * Worst case is O(1)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key currently in the priority queue\n\t */\n\tpublic Key minKey() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\treturn keys[pq[d]+d];\n\t}\n\n\t/**\n\t * Deletes the minimum key\n\t * Worst case is O(d*log-d(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the index associated with the minimum key\n\t */\n\tpublic int delMin() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\tint min = pq[d];\n\t\texch(0, --n);\n\t\tsink(0);\n\t\tqp[min+d] = -1;\n\t\tkeys[pq[n+d]+d] = null;\n\t\tpq[n+d] = -1;\n\t\treturn min;\n\t}\n\n\t/**\n\t * Gets the key associated with index i\n\t * Worst case is O(1)\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index is not in the queue\n\t * @return the key associated with index i\n\t */\n\tpublic Key keyOf(int i) {\n\t\tif (i < 0 || i >= nmax) throw new IllegalArgumentException();\n\t\tif (! contains(i)) throw new NoSuchElementException(\"Specified index is not in the queue\");\n\t\treturn keys[i+d];\n\t}\n\n\t/**\n\t * Changes the key associated with index i to the given key\n\t * If the given key is greater, Worst case is O(d*log-d(n))\n\t * If the given key is lower,   Worst case is O(log-d(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.lang.IllegalArgumentException if the index has no key associated with\n\t */\n\tpublic void changeKey(int i, Key key) {\n\t\tif (i < 0 || i >= nmax) throw new IllegalArgumentException();\n\t\tif (! contains(i)) throw new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tKey tmp = keys[i+d];\n\t\tkeys[i+d] = key;\n\t\tif (comp.compare(key, tmp) <= 0) { swim(qp[i+d]);}\n\t\telse \t\t\t\t\t\t\t { sink(qp[i+d]);}\n\t}\n\n\t/**\n\t * Decreases the key associated with index i to the given key\n\t * Worst case is O(log-d(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t * @throws java.lang.IllegalArgumentException if the given key is greater than the current key\n\t */\n\tpublic void decreaseKey(int i, Key key) {\n\t\tif (i < 0 || i >=nmax) throw new IllegalArgumentException();\n\t\tif (! contains(i)) throw new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (comp.compare(keys[i+d], key) <= 0) throw new IllegalArgumentException(\"Calling with this argument would not decrease the Key\");\n\t\tkeys[i+d] = key;\n\t\tswim(qp[i+d]);\n\t}\n\n\t/**\n\t * Increases the key associated with index i to the given key\n\t * Worst case is O(d*log-d(n))\n\t * @param i an index\n\t * @param key the key to associate with i\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the index has no key associated with\n\t * @throws java.lang.IllegalArgumentException if the given key is lower than the current key\n\t */\n\tpublic void increaseKey(int i, Key key) {\n\t\tif (i < 0 || i >=nmax) throw new IllegalArgumentException();\n\t\tif (! contains(i)) throw new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tif (comp.compare(keys[i+d], key) >= 0) throw new IllegalArgumentException(\"Calling with this argument would not increase the Key\");\n\t\tkeys[i+d] = key;\n\t\tsink(qp[i+d]);\n\t}\n\n\t/**\n\t * Deletes the key associated to the given index\n\t * Worst case is O(d*log-d(n))\n\t * @param i an index\n\t * @throws java.lang.IllegalArgumentException if the specified index is invalid\n\t * @throws java.util.NoSuchElementException if the given index has no key associated with\n\t */\n\tpublic void delete(int i) {\n\t\tif (i < 0 || i >= nmax) throw new IllegalArgumentException();\n\t\tif (! contains(i)) throw new NoSuchElementException(\"Specified index is not in the queue\");\n\t\tint idx = qp[i+d];\n\t\texch(idx, --n);\n\t\tswim(idx);\n\t\tsink(idx);\n\t\tkeys[i+d] = null;\n\t\tqp[i+d] = -1;\n\t}\n\t\n\t/***************************\n\t * General helper functions\n\t **************************/\n\t\n\t//Compares two keys\n\tprivate boolean greater(int i, int j) {\n\t\treturn comp.compare(keys[pq[i+d]+d], keys[pq[j+d]+d]) > 0;\n\t}\n\t\n\t//Exchanges two keys\n\tprivate void exch(int x, int y) {\n\t\tint i = x+d, j = y+d;\n\t\tint swap = pq[i];\n\t\tpq[i] = pq[j];\n\t\tpq[j] = swap;\n\t\tqp[pq[i]+d] = x;\n\t\tqp[pq[j]+d] = y;\n\t}\n\t\n\t/***************************\n\t * Functions for moving upward or downward\n\t **************************/\n\t\n\t//Moves upward\n\tprivate void swim(int i) {\n\t\tif (i > 0 && greater((i-1)/d, i)) {\n\t\t\texch(i, (i-1)/d);\n\t\t\tswim((i-1)/d);\n\t\t}\n\t}\n\t\n\t//Moves downward\n\tprivate void sink(int i) {\n\t\tif (d*i+1 >= n) return;\n\t\tint min = minChild(i);\n\t\twhile (min < n && greater(i, min)) {\n\t\t\texch(i, min);\n\t\t\ti = min;\n\t\t\tmin = minChild(i);\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Deletes the minimum child\n\t **************************/\n\t\n\t//Return the minimum child of i\n\tprivate int minChild(int i) {\n\t\tint loBound = d*i+1, hiBound = d*i+d;\n\t\tint min = loBound;\n\t\tfor (int cur = loBound; cur <= hiBound; cur++) {\n\t\t\tif (cur < n && greater(min, cur)) min = cur;\n\t\t}\n\t\treturn min;\n\t}\n\t\n\t/***************************\n\t * Iterator\n\t **************************/\n\t\n\t/**\n\t * Gets an Iterator over the indexes in the priority queue in ascending order\n\t * The Iterator does not implement the remove() method\n\t * iterator() : Worst case is O(n)\n\t * next() : \tWorst case is O(d*log-d(n))\n\t * hasNext() : \tWorst case is O(1)\n\t * @return an Iterator over the indexes in the priority queue in ascending order\n\t */\n\t\n\tpublic Iterator<Integer> iterator() {\n\t\treturn new MyIterator();\n\t}\n\t\n\t//Constructs an Iterator over the indices in linear time\n\tprivate class MyIterator implements Iterator<Integer> {\n\t\tIndexMultiwayMinPQ<Key> clone;\n\t\t\n\t\tpublic MyIterator() {\n\t\t\tclone = new IndexMultiwayMinPQ<Key>(nmax, comp, d);\n\t\t\tfor (int i = 0; i < n; i++) {\n\t\t\t\tclone.insert(pq[i+d], keys[pq[i+d]+d]);\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean hasNext() {\n\t\t\treturn !clone.isEmpty();\n\t\t}\n\t\t\n\t\tpublic Integer next() {\n                        if (!hasNext()) throw new NoSuchElementException();\n\t\t\treturn clone.delMin();\n\t\t}\n\t\t\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Comparator\n\t **************************/\n\t\n\t//default Comparator\n\tprivate class MyComparator implements Comparator<Key> {\n\t\t@Override\n\t\tpublic int compare(Key key1, Key key2) {\n\t\t\treturn ((Comparable<Key>) key1).compareTo(key2);\n\t\t}\n\t}\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/InplaceMSD.java",
    "content": "/******************************************************************************\n *  Compilation: javac InplaceMSD.java\n *  Execution:   java InplaceMSD < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/51radix/words3.txt\n *                https://algs4.cs.princeton.edu/51radix/shells.txt\n *\n *  Sort an array of strings or integers using in-place MSD radix sort.\n *\n *  % java InplaceMSD < shells.txt\n *  are\n *  by\n *  sea\n *  seashells\n *  seashells\n *  sells\n *  sells\n *  she\n *  she\n *  shells\n *  shore\n *  surely\n *  the\n *  the\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code InplaceMSD} class provides static methods for sorting an\n *  array of extended ASCII strings using in-place MSD radix sort.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/51radix\">Section 5.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Ivan Pesin\n */\n\npublic class InplaceMSD {\n    private static final int R             = 256;   // extended ASCII alphabet size\n    private static final int CUTOFF        =  15;   // cutoff to insertion sort\n\n    // do not instantiate\n    private InplaceMSD() { }\n\n   /**\n     * Rearranges the array of extended ASCII strings in ascending order.\n     * This is an unstable sorting algorithm.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(String[] a) {\n        int n = a.length;\n        sort(a, 0, n-1, 0);\n    }\n\n    // return dth character of s, -1 if d = length of string\n    private static int charAt(String s, int d) {\n        assert d >= 0 && d <= s.length();\n        if (d == s.length()) return -1;\n        return s.charAt(d);\n    }\n\n    // sort from a[lo] to a[hi], starting at the dth character\n    private static void sort(String[] a, int lo, int hi, int d) {\n\n        // cutoff to insertion sort for small subarrays\n        if (hi <= lo + CUTOFF) {\n            insertion(a, lo, hi, d);\n            return;\n        }\n\n        // compute frequency counts\n        int[] heads = new int[R+2];\n        int[] tails = new int[R+1];\n        for (int i = lo; i <= hi; i++) {\n            int c = charAt(a[i], d);\n            heads[c+2]++;\n        }\n\n        // transform counts to indices\n        heads[0] = lo;\n        for (int r = 0; r < R+1; r++) {\n            heads[r+1] += heads[r];\n            tails[r] = heads[r+1];\n        }\n\n        // sort by d-th character in-place\n        for (int r = 0; r < R+1; r++) {\n            while (heads[r] < tails[r]) {\n                int c = charAt(a[heads[r]], d);\n                while (c + 1 != r) {\n                    exch(a, heads[r], heads[c+1]++);\n                    c = charAt(a[heads[r]], d);\n                }\n                heads[r]++;\n            }\n        }\n\n        // recursively sort for each character (excludes sentinel -1)\n        for (int r = 0; r < R; r++)\n            sort(a, tails[r], tails[r+1] - 1, d+1);\n    }\n\n\n    // insertion sort a[lo..hi], starting at dth character\n    private static void insertion(String[] a, int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], d); j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(String[] a, int i, int j) {\n        String temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n    // is v less than w, starting at character d\n    private static boolean less(String v, String w, int d) {\n        // assert v.substring(0, d).equals(w.substring(0, d));\n        for (int i = d; i < Math.min(v.length(), w.length()); i++) {\n            if (v.charAt(i) < w.charAt(i)) return true;\n            if (v.charAt(i) > w.charAt(i)) return false;\n        }\n        return v.length() < w.length();\n    }\n\n\n    /**\n     * Reads in a sequence of extended ASCII strings from standard input;\n     * in-place MSD radix sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        int n = a.length;\n        sort(a);\n        for (int i = 0; i < n; i++)\n            StdOut.println(a[i]);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Insertion.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Insertion.java\n *  Execution:    java Insertion < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/21elementary/tiny.txt\n *                https://algs4.cs.princeton.edu/21elementary/words3.txt\n *\n *  Sorts a sequence of strings from standard input using insertion sort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Insertion < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Insertion < words3.txt\n *  all bad bed bug dad ... yes yet zoo   [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\n\n/**\n *  The {@code Insertion} class provides static methods for sorting an\n *  array using insertion sort.\n *  <p>\n *  In the worst case, this implementation makes ~ &frac12; <em>n</em><sup>2</sup>\n *  compares and ~ &frac12; <em>n</em><sup>2</sup> exchanges to sort an array\n *  of length <em>n</em>. So, it is not suitable for sorting large arbitrary\n *  arrays. More precisely, the number of exchanges is exactly equal to the\n *  number of inversions. So, for example, it sorts a partially-sorted array\n *  in linear time.\n *  <p>\n *  This sorting algorithm is stable.\n *  It uses &Theta;(1) extra memory (not including the input array).\n *  <p>\n *  See <a href=\"https://algs4.cs.princeton.edu/21elementary/InsertionPedantic.java.html\">InsertionPedantic.java</a>\n *  for a version that eliminates the compiler warning.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/21elementary\">Section 2.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Insertion {\n\n    // This class should not be instantiated.\n    private Insertion() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        int n = a.length;\n        for (int i = 1; i < n; i++) {\n            for (int j = i; j > 0 && less(a[j], a[j-1]); j--) {\n                exch(a, j, j-1);\n            }\n            assert isSorted(a, 0, i);\n        }\n        assert isSorted(a);\n    }\n\n    /**\n     * Rearranges the subarray a[lo..hi) in ascending order, using the natural order.\n     * @param a the array to be sorted\n     * @param lo left endpoint (inclusive)\n     * @param hi right endpoint (exclusive)\n     */\n    public static void sort(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i < hi; i++) {\n            for (int j = i; j > lo && less(a[j], a[j-1]); j--) {\n                exch(a, j, j-1);\n            }\n        }\n        assert isSorted(a, lo, hi);\n    }\n\n    /**\n     * Rearranges the array in ascending order, using a comparator.\n     * @param a the array\n     * @param comparator the comparator specifying the order\n     */\n    public static void sort(Object[] a, Comparator comparator) {\n        int n = a.length;\n        for (int i = 1; i < n; i++) {\n            for (int j = i; j > 0 && less(a[j], a[j-1], comparator); j--) {\n                exch(a, j, j-1);\n            }\n            assert isSorted(a, 0, i, comparator);\n        }\n        assert isSorted(a, comparator);\n    }\n\n    /**\n     * Rearranges the subarray a[lo..hi) in ascending order, using a comparator.\n     * @param a the array\n     * @param lo left endpoint (inclusive)\n     * @param hi right endpoint (exclusive)\n     * @param comparator the comparator specifying the order\n     */\n    public static void sort(Object[] a, int lo, int hi, Comparator comparator) {\n        for (int i = lo + 1; i < hi; i++) {\n            for (int j = i; j > lo && less(a[j], a[j-1], comparator); j--) {\n                exch(a, j, j-1);\n            }\n        }\n        assert isSorted(a, lo, hi, comparator);\n    }\n\n\n    // return a permutation that gives the elements in a[] in ascending order\n    // do not change the original array a[]\n    /**\n     * Returns a permutation that gives the elements in the array in ascending order.\n     * @param a the array\n     * @return a permutation {@code p[]} such that {@code a[p[0]]}, {@code a[p[1]]},\n     *    ..., {@code a[p[n-1]]} are in ascending order\n     */\n    public static int[] indexSort(Comparable[] a) {\n        int n = a.length;\n        int[] index = new int[n];\n        for (int i = 0; i < n; i++)\n            index[i] = i;\n\n        for (int i = 1; i < n; i++)\n            for (int j = i; j > 0 && less(a[index[j]], a[index[j-1]]); j--)\n                exch(index, j, j-1);\n\n        return index;\n    }\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // is v < w ?\n    private static boolean less(Object v, Object w, Comparator comparator) {\n        return comparator.compare(v, w) < 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n    // exchange a[i] and a[j]  (for indirect sort)\n    private static void exch(int[] a, int i, int j) {\n        int swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length);\n    }\n\n    // is the array a[lo..hi) sorted\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i < hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    private static boolean isSorted(Object[] a, Comparator comparator) {\n        return isSorted(a, 0, a.length, comparator);\n    }\n\n    // is the array a[lo..hi) sorted\n    private static boolean isSorted(Object[] a, int lo, int hi, Comparator comparator) {\n        for (int i = lo + 1; i < hi; i++)\n            if (less(a[i], a[i-1], comparator)) return false;\n        return true;\n    }\n\n   // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; insertion sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Insertion.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/InsertionX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac InsertionX.java\n *  Execution:    java InsertionX < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/21elementary/tiny.txt\n *                https://algs4.cs.princeton.edu/21elementary/words3.txt\n *\n *  Sorts a sequence of strings from standard input using an optimized\n *  version of insertion sort that uses half exchanges instead of\n *  full exchanges to reduce data movement..\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java InsertionX < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java InsertionX < words3.txt\n *  all bad bed bug dad ... yes yet zoo   [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n/**\n *  The {@code InsertionX} class provides static methods for sorting\n *  an array using an optimized version of insertion sort (with half exchanges\n *  and a sentinel).\n *  <p>\n *  In the worst case, this implementation makes ~ 1/2 <em>n</em><sup>2</sup>\n *  compares to sort an array of length <em>n</em>.\n *  So, it is not suitable for sorting large arrays\n *  (unless the number of inversions is small).\n *  <p>\n *  This sorting algorithm is stable.\n *  It uses &Theta;(1) extra memory (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/21elementary\">Section 2.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class InsertionX {\n\n    // This class should not be instantiated.\n    private InsertionX() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        int n = a.length;\n\n        // put smallest element in position to serve as sentinel\n        int exchanges = 0;\n        for (int i = n-1; i > 0; i--) {\n            if (less(a[i], a[i-1])) {\n                exch(a, i, i-1);\n                exchanges++;\n            }\n        }\n        if (exchanges == 0) return;\n\n\n        // insertion sort with half-exchanges\n        for (int i = 2; i < n; i++) {\n            Comparable v = a[i];\n            int j = i;\n            while (less(v, a[j-1])) {\n                a[j] = a[j-1];\n                j--;\n            }\n            a[j] = v;\n        }\n\n        assert isSorted(a);\n    }\n\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; insertion sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        InsertionX.sort(a);\n        show(a);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Interval1D.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Interval1D.java\n *  Execution:    java Interval1D\n *  Dependencies: StdOut.java\n *\n *  1-dimensional interval data type.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\nimport java.util.Comparator;\n\n/**\n *  The {@code Interval1D} class represents a one-dimensional interval.\n *  The interval is <em>closed</em>—it contains both endpoints.\n *  Intervals are immutable: their values cannot be changed after they are created.\n *  The class {@code Interval1D} includes methods for checking whether\n *  an interval contains a point and determining whether two intervals intersect.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Interval1D {\n\n    /**\n     * Compares two intervals by min endpoint.\n     */\n    public static final Comparator<Interval1D> MIN_ENDPOINT_ORDER  = new MinEndpointComparator();\n\n    /**\n     * Compares two intervals by max endpoint.\n     */\n    public static final Comparator<Interval1D> MAX_ENDPOINT_ORDER = new MaxEndpointComparator();\n\n    /**\n     * Compares two intervals by length.\n     */\n    public static final Comparator<Interval1D> LENGTH_ORDER = new LengthComparator();\n\n    private final double min;\n    private final double max;\n\n    /**\n     * Initializes a closed interval [min, max].\n     *\n     * @param  min the smaller endpoint\n     * @param  max the larger endpoint\n     * @throws IllegalArgumentException if the min endpoint is greater than the max endpoint\n     * @throws IllegalArgumentException if either {@code min} or {@code max}\n     *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY} or\n     *         {@code Double.NEGATIVE_INFINITY}\n\n     */\n    public Interval1D(double min, double max) {\n        if (Double.isInfinite(min) || Double.isInfinite(max))\n            throw new IllegalArgumentException(\"Endpoints must be finite\");\n        if (Double.isNaN(min) || Double.isNaN(max))\n            throw new IllegalArgumentException(\"Endpoints cannot be NaN\");\n\n        // convert -0.0 to +0.0\n        if (min == 0.0) min = 0.0;\n        if (max == 0.0) max = 0.0;\n\n        if (min <= max) {\n            this.min = min;\n            this.max = max;\n        }\n        else throw new IllegalArgumentException(\"Illegal interval\");\n    }\n\n    /**\n     * Returns the left endpoint of this interval.\n     *\n     * @return the left endpoint of this interval\n     * @deprecated Replaced by {@link #min()}.\n     */\n    @Deprecated\n    public double left() {\n        return min;\n    }\n\n    /**\n     * Returns the right endpoint of this interval.\n     * @return the right endpoint of this interval\n     * @deprecated Replaced by {@link #max()}.\n     */\n    @Deprecated\n    public double right() {\n        return max;\n    }\n\n    /**\n     * Returns the min endpoint of this interval.\n     *\n     * @return the min endpoint of this interval\n     */\n    public double min() {\n        return min;\n    }\n\n    /**\n     * Returns the max endpoint of this interval.\n     *\n     * @return the max endpoint of this interval\n     */\n    public double max() {\n        return max;\n    }\n\n    /**\n     * Returns true if this interval intersects the specified interval.\n     *\n     * @param  that the other interval\n     * @return {@code true} if this interval intersects the argument interval;\n     *         {@code false} otherwise\n     */\n    public boolean intersects(Interval1D that) {\n        if (this.max < that.min) return false;\n        if (that.max < this.min) return false;\n        return true;\n    }\n\n    /**\n     * Returns true if this interval contains the specified interval.\n     *\n     * @param  that the other interval\n     * @return {@code true} if this interval contains the argument interval;\n     *         {@code false} otherwise\n     */\n    public boolean contains(Interval1D that) {\n        return (this.max >= that.max) && (this.min <= that.min);\n    }\n\n    /**\n     * Returns true if this interval contains the specified value.\n     *\n     * @param x the value\n     * @return {@code true} if this interval contains the value {@code x};\n     *         {@code false} otherwise\n     */\n    public boolean contains(double x) {\n        return (min <= x) && (x <= max);\n    }\n\n    /**\n     * Returns the length of this interval.\n     *\n     * @return the length of this interval (max - min)\n     */\n    public double length() {\n        return max - min;\n    }\n\n    /**\n     * Returns a string representation of this interval.\n     *\n     * @return a string representation of this interval in the form [min, max]\n     */\n    public String toString() {\n        return \"[\" + min + \", \" + max + \"]\";\n    }\n\n    /**\n     * Compares this transaction to the specified object.\n     *\n     * @param  other the other interval\n     * @return {@code true} if this interval equals the other interval;\n     *         {@code false} otherwise\n     */\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Interval1D that = (Interval1D) other;\n        return this.min == that.min && this.max == that.max;\n    }\n\n    /**\n     * Returns an integer hash code for this interval.\n     *\n     * @return an integer hash code for this interval\n     */\n    public int hashCode() {\n        int hash1 = ((Double) min).hashCode();\n        int hash2 = ((Double) max).hashCode();\n        return 31*hash1 + hash2;\n    }\n\n    // ascending order of min endpoint, breaking ties by max endpoint\n    private static class MinEndpointComparator implements Comparator<Interval1D> {\n        public int compare(Interval1D a, Interval1D b) {\n            if      (a.min < b.min) return -1;\n            else if (a.min > b.min) return +1;\n            else if (a.max < b.max) return -1;\n            else if (a.max > b.max) return +1;\n            else                    return  0;\n        }\n    }\n\n    // ascending order of max endpoint, breaking ties by min endpoint\n    private static class MaxEndpointComparator implements Comparator<Interval1D> {\n        public int compare(Interval1D a, Interval1D b) {\n            if      (a.max < b.max) return -1;\n            else if (a.max > b.max) return +1;\n            else if (a.min < b.min) return -1;\n            else if (a.min > b.min) return +1;\n            else                    return  0;\n        }\n    }\n\n    // ascending order of length\n    private static class LengthComparator implements Comparator<Interval1D> {\n        public int compare(Interval1D a, Interval1D b) {\n            double alen = a.length();\n            double blen = b.length();\n            if      (alen < blen) return -1;\n            else if (alen > blen) return +1;\n            else                  return  0;\n        }\n    }\n\n\n\n\n    /**\n     * Unit tests the {@code Interval1D} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Interval1D[] intervals = new Interval1D[4];\n        intervals[0] = new Interval1D(15.0, 33.0);\n        intervals[1] = new Interval1D(45.0, 60.0);\n        intervals[2] = new Interval1D(20.0, 70.0);\n        intervals[3] = new Interval1D(46.0, 55.0);\n\n        StdOut.println(\"Unsorted\");\n        for (int i = 0; i < intervals.length; i++)\n            StdOut.println(intervals[i]);\n        StdOut.println();\n\n        StdOut.println(\"Sort by min endpoint\");\n        Arrays.sort(intervals, Interval1D.MIN_ENDPOINT_ORDER);\n        for (int i = 0; i < intervals.length; i++)\n            StdOut.println(intervals[i]);\n        StdOut.println();\n\n        StdOut.println(\"Sort by max endpoint\");\n        Arrays.sort(intervals, Interval1D.MAX_ENDPOINT_ORDER);\n        for (int i = 0; i < intervals.length; i++)\n            StdOut.println(intervals[i]);\n        StdOut.println();\n\n        StdOut.println(\"Sort by length\");\n        Arrays.sort(intervals, Interval1D.LENGTH_ORDER);\n        for (int i = 0; i < intervals.length; i++)\n            StdOut.println(intervals[i]);\n        StdOut.println();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Interval2D.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Interval2D.java\n *  Execution:    java Interval2D\n *  Dependencies: StdOut.java Interval1D.java StdDraw.java\n *\n *  2-dimensional interval data type.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Interval2D} class represents a closed two-dimensional interval,\n *  which represents all points (x, y) with both {@code xmin <= x <= xmax} and\n *  {@code ymin <= y <= ymax}.\n *  Two-dimensional intervals are immutable: their values cannot be changed\n *  after they are created.\n *  The class {@code Interval2D} includes methods for checking whether\n *  a two-dimensional interval contains a point and determining whether\n *  two two-dimensional intervals intersect.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Interval2D {\n    private final Interval1D x;\n    private final Interval1D y;\n\n    /**\n     * Initializes a two-dimensional interval.\n     * @param x the one-dimensional interval of x-coordinates\n     * @param y the one-dimensional interval of y-coordinates\n     */\n    public Interval2D(Interval1D x, Interval1D y) {\n        this.x = x;\n        this.y = y;\n    }\n\n    /**\n     * Does this two-dimensional interval intersect that two-dimensional interval?\n     * @param that the other two-dimensional interval\n     * @return true if this two-dimensional interval intersects\n     *    that two-dimensional interval; false otherwise\n     */\n    public boolean intersects(Interval2D that) {\n        if (!this.x.intersects(that.x)) return false;\n        if (!this.y.intersects(that.y)) return false;\n        return true;\n    }\n\n    /**\n     * Does this two-dimensional interval contain that two-dimensional interval?\n     * @param that the other two-dimensional interval\n     * @return true if this two-dimensional interval contains\n     *    that two-dimensional interval; false otherwise\n     */\n    public boolean contains(Interval2D that) {\n        return this.x.contains(that.x) && this.y.contains(that.y);\n    }\n\n    /**\n     * Does this two-dimensional interval contain the point p?\n     * @param p the two-dimensional point\n     * @return true if this two-dimensional interval contains the point p; false otherwise\n     */\n    public boolean contains(Point2D p) {\n        return x.contains(p.x())  && y.contains(p.y());\n    }\n\n    /**\n     * Returns the area of this two-dimensional interval.\n     * @return the area of this two-dimensional interval\n     */\n    public double area() {\n        return x.length() * y.length();\n    }\n\n    /**\n     * Returns a string representation of this two-dimensional interval.\n     * @return a string representation of this two-dimensional interval\n     *    in the form [xmin, xmax] x [ymin, ymax]\n     */\n    public String toString() {\n        return x + \" x \" + y;\n    }\n\n    /**\n     * Does this interval equal the other interval?\n     * @param other the other interval\n     * @return true if this interval equals the other interval; false otherwise\n     */\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Interval2D that = (Interval2D) other;\n        return this.x.equals(that.x) && this.y.equals(that.y);\n    }\n\n\n    /**\n     * Returns an integer hash code for this interval.\n     * @return an integer hash code for this interval\n     */\n    public int hashCode() {\n        int hash1 = x.hashCode();\n        int hash2 = y.hashCode();\n        return 31*hash1 + hash2;\n    }\n\n    /**\n     * Draws this two-dimensional interval to standard draw.\n     */\n    public void draw() {\n        double xc = (x.min() + x.max()) / 2.0;\n        double yc = (y.min() + y.max()) / 2.0;\n        StdDraw.rectangle(xc, yc, x.length() / 2.0, y.length() / 2.0);\n    }\n\n    /**\n     * Unit tests the {@code Interval2D} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        double xmin = Double.parseDouble(args[0]);\n        double xmax = Double.parseDouble(args[1]);\n        double ymin = Double.parseDouble(args[2]);\n        double ymax = Double.parseDouble(args[3]);\n        int trials = Integer.parseInt(args[4]);\n\n        Interval1D xInterval = new Interval1D(xmin, xmax);\n        Interval1D yInterval = new Interval1D(ymin, ymax);\n        Interval2D box = new Interval2D(xInterval, yInterval);\n        box.draw();\n\n        Counter counter = new Counter(\"hits\");\n        for (int t = 0; t < trials; t++) {\n            double x = StdRandom.uniformDouble(0.0, 1.0);\n            double y = StdRandom.uniformDouble(0.0, 1.0);\n            Point2D point = new Point2D(x, y);\n\n            if (box.contains(point)) counter.increment();\n            else                     point.draw();\n        }\n\n        StdOut.println(counter);\n        StdOut.printf(\"box area = %.2f\\n\", box.area());\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Inversions.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Inversions.java\n *  Execution:    java Inversions < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *\n *  Read array of n integers and count number of inversions in n log n time.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Inversions} class provides static methods to count the\n *  number of <em>inversions</em> in either an array of integers or comparables.\n *  An inversion in an array {@code a[]} is a pair of indicies {@code i} and\n *  {@code j} such that {@code i < j} and {@code a[i] > a[j]}.\n *  <p>\n *  This implementation uses a generalization of mergesort. The <em>count</em>\n *  operation takes &Theta;(<em>n</em> log <em>n</em>) time to count the\n *  number of inversions in any array of length <em>n</em> (assuming\n *  comparisons take constant time).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/22mergesort\">Section 2.2</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Inversions {\n\n    // do not instantiate\n    private Inversions() { }\n\n    // merge and count\n    private static long merge(int[] a, int[] aux, int lo, int mid, int hi) {\n        long inversions = 0;\n\n        // copy to aux[]\n        for (int k = lo; k <= hi; k++) {\n            aux[k] = a[k];\n        }\n\n        // merge back to a[]\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)           a[k] = aux[j++];\n            else if (j > hi)            a[k] = aux[i++];\n            else if (aux[j] < aux[i]) { a[k] = aux[j++]; inversions += (mid - i + 1); }\n            else                        a[k] = aux[i++];\n        }\n        return inversions;\n    }\n\n    // return the number of inversions in the subarray b[lo..hi]\n    // side effect b[lo..hi] is rearranged in ascending order\n    private static long count(int[] a, int[] b, int[] aux, int lo, int hi) {\n        long inversions = 0;\n        if (hi <= lo) return 0;\n        int mid = lo + (hi - lo) / 2;\n        inversions += count(a, b, aux, lo, mid);\n        inversions += count(a, b, aux, mid+1, hi);\n        inversions += merge(b, aux, lo, mid, hi);\n        assert inversions == brute(a, lo, hi);\n        return inversions;\n    }\n\n\n    /**\n     * Returns the number of inversions in the integer array.\n     * The argument array is not modified.\n     * @param  a the array\n     * @return the number of inversions in the array. An inversion is a pair of\n     *         indicies {@code i} and {@code j} such that {@code i < j}\n     *         and {@code a[i] > a[j]}.\n     */\n    public static long count(int[] a) {\n        int[] b   = new int[a.length];\n        int[] aux = new int[a.length];\n        for (int i = 0; i < a.length; i++)\n            b[i] = a[i];\n        long inversions = count(a, b, aux, 0, a.length - 1);\n        return inversions;\n    }\n\n\n\n    // merge and count (Comparable version)\n    private static <Key extends Comparable<Key>> long merge(Key[] a, Key[] aux, int lo, int mid, int hi) {\n        long inversions = 0;\n\n        // copy to aux[]\n        for (int k = lo; k <= hi; k++) {\n            aux[k] = a[k];\n        }\n\n        // merge back to a[]\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)                a[k] = aux[j++];\n            else if (j > hi)                 a[k] = aux[i++];\n            else if (less(aux[j], aux[i])) { a[k] = aux[j++]; inversions += (mid - i + 1); }\n            else                             a[k] = aux[i++];\n        }\n        return inversions;\n    }\n\n    // return the number of inversions in the subarray b[lo..hi]\n    // side effect b[lo..hi] is rearranged in ascending order\n    private static <Key extends Comparable<Key>> long count(Key[] a, Key[] b, Key[] aux, int lo, int hi) {\n        long inversions = 0;\n        if (hi <= lo) return 0;\n        int mid = lo + (hi - lo) / 2;\n        inversions += count(a, b, aux, lo, mid);\n        inversions += count(a, b, aux, mid+1, hi);\n        inversions += merge(b, aux, lo, mid, hi);\n        assert inversions == brute(a, lo, hi);\n        return inversions;\n    }\n\n\n    /**\n     * Returns the number of inversions in the comparable array.\n     * The argument array is not modified.\n     * @param  a the array\n     * @param <Key> the inferred type of the elements in the array\n     * @return the number of inversions in the array. An inversion is a pair of\n     *         indicies {@code i} and {@code j} such that {@code i < j}\n     *         and {@code a[i].compareTo(a[j]) > 0}.\n     */\n    public static <Key extends Comparable<Key>> long count(Key[] a) {\n        Key[] b   = a.clone();\n        Key[] aux = a.clone();\n        long inversions = count(a, b, aux, 0, a.length - 1);\n        return inversions;\n    }\n\n\n    // is v < w ?\n    private static <Key extends Comparable<Key>> boolean less(Key v, Key w) {\n        return (v.compareTo(w) < 0);\n    }\n\n    // count number of inversions in a[lo..hi] via brute force (for debugging only)\n    private static <Key extends Comparable<Key>> long brute(Key[] a, int lo, int hi) {\n        long inversions = 0;\n        for (int i = lo; i <= hi; i++)\n            for (int j = i + 1; j <= hi; j++)\n                if (less(a[j], a[i])) inversions++;\n        return inversions;\n    }\n\n    // count number of inversions in a[lo..hi] via brute force (for debugging only)\n    private static long brute(int[] a, int lo, int hi) {\n        long inversions = 0;\n        for (int i = lo; i <= hi; i++)\n            for (int j = i + 1; j <= hi; j++)\n                if (a[j] < a[i]) inversions++;\n        return inversions;\n    }\n\n    /**\n     * Reads a sequence of integers from standard input and\n     * prints the number of inversions to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int[] a = StdIn.readAllInts();\n        int n = a.length;\n        Integer[] b = new Integer[n];\n        for (int i = 0; i < n; i++)\n            b[i] = a[i];\n        StdOut.println(Inversions.count(a));\n        StdOut.println(Inversions.count(b));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/KMP.java",
    "content": "/******************************************************************************\n *  Compilation:  javac KMP.java\n *  Execution:    java KMP pattern text\n *  Dependencies: StdOut.java\n *\n *  Reads in two strings, the pattern and the input text, and\n *  searches for the pattern in the input text using the\n *  KMP algorithm.\n *\n *  % java KMP abracadabra abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:               abracadabra\n *\n *  % java KMP rab abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:         rab\n *\n *  % java KMP bcara abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:                                   bcara\n *\n *  % java KMP rabrabracad abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:                        rabrabracad\n *\n *  % java KMP abacad abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern: abacad\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code KMP} class finds the first occurrence of a pattern string\n *  in a text string.\n *  <p>\n *  This implementation uses a version of the Knuth-Morris-Pratt substring search\n *  algorithm. The version takes time proportional to <em>n</em> + <em>m R</em>\n *  in the worst case, where <em>n</em> is the length of the text string,\n *  <em>m</em> is the length of the pattern, and <em>R</em> is the alphabet size.\n *  It uses extra space proportional to <em>m R</em>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/53substring\">Section 5.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class KMP {\n    private final int R;       // the radix\n    private final int m;       // length of pattern\n    private int[][] dfa;       // the KMP automaton\n\n    /**\n     * Preprocesses the pattern string.\n     *\n     * @param pat the pattern string\n     */\n    public KMP(String pat) {\n        this.R = 256;\n        this.m = pat.length();\n\n        // build DFA from pattern\n        dfa = new int[R][m];\n        dfa[pat.charAt(0)][0] = 1;\n        for (int x = 0, j = 1; j < m; j++) {\n            for (int c = 0; c < R; c++)\n                dfa[c][j] = dfa[c][x];     // Copy mismatch cases.\n            dfa[pat.charAt(j)][j] = j+1;   // Set match case.\n            x = dfa[pat.charAt(j)][x];     // Update restart state.\n        }\n    }\n\n    /**\n     * Preprocesses the pattern string.\n     *\n     * @param pattern the pattern string\n     * @param R the alphabet size\n     */\n    public KMP(char[] pattern, int R) {\n        this.R = R;\n        this.m = pattern.length;\n\n        // build DFA from pattern\n        int m = pattern.length;\n        dfa = new int[R][m];\n        dfa[pattern[0]][0] = 1;\n        for (int x = 0, j = 1; j < m; j++) {\n            for (int c = 0; c < R; c++)\n                dfa[c][j] = dfa[c][x];     // Copy mismatch cases.\n            dfa[pattern[j]][j] = j+1;      // Set match case.\n            x = dfa[pattern[j]][x];        // Update restart state.\n        }\n    }\n\n    /**\n     * Returns the index of the first occurrence of the pattern string\n     * in the text string.\n     *\n     * @param  txt the text string\n     * @return the index of the first occurrence of the pattern string\n     *         in the text string; N if no such match\n     */\n    public int search(String txt) {\n\n        // simulate operation of DFA on text\n        int n = txt.length();\n        int i, j;\n        for (i = 0, j = 0; i < n && j < m; i++) {\n            j = dfa[txt.charAt(i)][j];\n        }\n        if (j == m) return i - m;    // found\n        return n;                    // not found\n    }\n\n    /**\n     * Returns the index of the first occurrence of the pattern string\n     * in the text string.\n     *\n     * @param  text the text string\n     * @return the index of the first occurrence of the pattern string\n     *         in the text string; N if no such match\n     */\n    public int search(char[] text) {\n\n        // simulate operation of DFA on text\n        int n = text.length;\n        int i, j;\n        for (i = 0, j = 0; i < n && j < m; i++) {\n            j = dfa[text[i]][j];\n        }\n        if (j == m) return i - m;    // found\n        return n;                    // not found\n    }\n\n\n    /**\n     * Takes a pattern string and an input string as command-line arguments;\n     * searches for the pattern string in the text string; and prints\n     * the first occurrence of the pattern string in the text string.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String pat = args[0];\n        String txt = args[1];\n        char[] pattern = pat.toCharArray();\n        char[] text    = txt.toCharArray();\n\n        KMP kmp1 = new KMP(pat);\n        int offset1 = kmp1.search(txt);\n\n        KMP kmp2 = new KMP(pattern, 256);\n        int offset2 = kmp2.search(text);\n\n        // print results\n        StdOut.println(\"text:    \" + txt);\n\n        StdOut.print(\"pattern: \");\n        for (int i = 0; i < offset1; i++)\n            StdOut.print(\" \");\n        StdOut.println(pat);\n\n        StdOut.print(\"pattern: \");\n        for (int i = 0; i < offset2; i++)\n            StdOut.print(\" \");\n        StdOut.println(pat);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/KWIK.java",
    "content": "/******************************************************************************\n *  Compilation:  javac KWIK.java\n *  Execution:    java KWIK file.txt\n *  Dependencies: StdIn.java StdOut.java In.java SuffixArray.java\n *  Data files:   https://algs4.cs.princeton.edu/63suffix/tale.txt\n *                https://algs4.cs.princeton.edu/63suffix/mobydick.txt\n *\n *  Keyword-in-context search.\n *\n *  %  java KWIK tale.txt 15\n *  majesty\n *   most gracious majesty king george th\n *  rnkeys and the majesty of the law fir\n *  on against the majesty of the people\n *  se them to his majestys chief secreta\n *  h lists of his majestys forces and of\n *\n *  the worst\n *  w the best and the worst are known to y\n *  f them give me the worst first there th\n *  for in case of the worst is a friend in\n *  e roomdoor and the worst is over then a\n *  pect mr darnay the worst its the wisest\n *  is his brother the worst of a bad race\n *  ss in them for the worst of health for\n *   you have seen the worst of her agitati\n *  cumwented into the worst of luck buuust\n *  n your brother the worst of the bad rac\n *   full share in the worst of the day pla\n *  mes to himself the worst of the strife\n *  f times it was the worst of times it wa\n *  ould hope that the worst was over well\n *  urage business the worst will be over i\n *  clesiastics of the worst world worldly\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code KWIK} class provides a {@link SuffixArray} client for computing\n *  all occurrences of a keyword in a given string, with surrounding context.\n *  This is known as <em>keyword-in-context search</em>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/63suffix\">Section 6.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class KWIK {\n\n    // Do not instantiate.\n    private KWIK() { }\n\n    /**\n     * Reads a string from a file specified as the first\n     * command-line argument; read an integer k specified as the\n     * second command line argument; then repeatedly processes\n     * use queries, printing all occurrences of the given query\n     * string in the text string with k characters of surrounding\n     * context on either side.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        int context = Integer.parseInt(args[1]);\n\n        // read in text\n        String text = in.readAll().replaceAll(\"\\\\s+\", \" \");\n        int n = text.length();\n\n        // build suffix array\n        SuffixArray sa = new SuffixArray(text);\n\n        // find all occurrences of queries and give context\n        while (StdIn.hasNextLine()) {\n            String query = StdIn.readLine();\n            for (int i = sa.rank(query); i < n; i++) {\n                int from1 = sa.index(i);\n                int to1   = Math.min(n, from1 + query.length());\n                if (!query.equals(text.substring(from1, to1))) break;\n                int from2 = Math.max(0, sa.index(i) - context);\n                int to2   = Math.min(n, sa.index(i) + context + query.length());\n                StdOut.println(text.substring(from2, to2));\n            }\n            StdOut.println();\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Knuth.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Knuth.java\n *  Execution:    java Knuth < list.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/11model/cards.txt\n *                https://algs4.cs.princeton.edu/11model/cardsUnicode.txt\n *\n *  Reads in a list of strings and prints them in random order.\n *  The Knuth (or Fisher-Yates) shuffling algorithm guarantees\n *  to rearrange the elements in uniformly random order, under\n *  the assumption that Math.random() generates independent and\n *  uniformly distributed numbers between 0 and 1.\n *\n *  % more cards.txt\n *  2C 3C 4C 5C 6C 7C 8C 9C 10C JC QC KC AC\n *  2D 3D 4D 5D 6D 7D 8D 9D 10D JD QD KD AD\n *  2H 3H 4H 5H 6H 7H 8H 9H 10H JH QH KH AH\n *  2S 3S 4S 5S 6S 7S 8S 9S 10S JS QS KS AS\n *\n *  % java Knuth < cards.txt\n *  6H\n *  9C\n *  8H\n *  7C\n *  JS\n *  ...\n *  KH\n *\n *  % more cardsUnicode.txt\n *  2♣ 3♣ 4♣ 5♣ 6♣ 7♣ 8♣ 9♣ 10♣ J♣ Q♣ K♣ A♣\n *  2♦ 3♦ 4♦ 5♦ 6♦ 7♦ 8♦ 9♦ 10♦ J♦ Q♦ K♦ A♦\n *  2♥ 3♥ 4♥ 5♥ 6♥ 7♥ 8♥ 9♥ 10♥ J♥ Q♥ K♥ A♥\n *  2♠ 3♠ 4♠ 5♠ 6♠ 7♠ 8♠ 9♠ 10♠ J♠ Q♠ K♠ A♠\n *\n *  % java Knuth < cardsUnicode.txt\n *  2♠\n *  K♥\n *  6♥\n *  5♣\n *  J♣\n *  ...\n *  A♦\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Knuth} class provides a client for reading in a\n *  sequence of strings and <em>shuffling</em> them using the Knuth (or Fisher-Yates)\n *  shuffling algorithm. This algorithm guarantees to rearrange the\n *  elements in uniformly random order, under\n *  the assumption that Math.random() generates independent and\n *  uniformly distributed numbers between 0 and 1.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/11model\">Section 1.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  See {@link StdRandom} for versions that shuffle arrays and\n *  subarrays of objects, doubles, and ints.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Knuth {\n\n    // this class should not be instantiated\n    private Knuth() { }\n\n    /**\n     * Rearranges an array of objects in uniformly random order\n     * (under the assumption that {@code Math.random()} generates independent\n     * and uniformly distributed numbers between 0 and 1).\n     * @param a the array to be shuffled\n     */\n    public static void shuffle(Object[] a) {\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            // choose index uniformly in [0, i]\n            int r = (int) (Math.random() * (i + 1));\n            Object swap = a[r];\n            a[r] = a[i];\n            a[i] = swap;\n        }\n    }\n\n    /**\n     * Rearranges an array of objects in uniformly random order\n     * (under the assumption that {@code Math.random()} generates independent\n     * and uniformly distributed numbers between 0 and 1).\n     * @param a the array to be shuffled\n     */\n    public static void shuffleAlternate(Object[] a) {\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            // choose index uniformly in [i, n-1]\n            int r = i + (int) (Math.random() * (n - i));\n            Object swap = a[r];\n            a[r] = a[i];\n            a[i] = swap;\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input, shuffles\n     * them, and prints out the results.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read in the data\n        String[] a = StdIn.readAllStrings();\n\n        // shuffle the array\n        Knuth.shuffle(a);\n\n        // print results.\n        for (int i = 0; i < a.length; i++)\n            StdOut.println(a[i]);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/KosarajuSharirSCC.java",
    "content": "/******************************************************************************\n *  Compilation:  javac KosarajuSharirSCC.java\n *  Execution:    java KosarajuSharirSCC filename.txt\n *  Dependencies: Digraph.java TransitiveClosure.java StdOut.java In.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Compute the strongly-connected components of a digraph using the\n *  Kosaraju-Sharir algorithm.\n *\n *  Runs in O(E + V) time.\n *\n *  % java KosarajuSharirSCC tinyDG.txt\n *  5 strong components\n *  1\n *  0 2 3 4 5\n *  9 10 11 12\n *  6 8\n *  7\n *\n *  % java KosarajuSharirSCC mediumDG.txt\n *  10 strong components\n *  21\n *  2 5 6 8 9 11 12 13 15 16 18 19 22 23 25 26 28 29 30 31 32 33 34 35 37 38 39 40 42 43 44 46 47 48 49\n *  14\n *  3 4 17 20 24 27 36\n *  41\n *  7\n *  45\n *  1\n *  0\n *  10\n *\n *  % java -Xss50m KosarajuSharirSCC mediumDG.txt\n *  25 strong components\n *  7 11 32 36 61 84 95 116 121 128 230   ...\n *  28 73 80 104 115 143 149 164 184 185  ...\n *  38 40 200 201 207 218 286 387 418 422 ...\n *  12 14 56 78 87 103 216 269 271 272    ...\n *  42 48 112 135 160 217 243 246 273 346 ...\n *  46 76 96 97 224 237 297 303 308 309   ...\n *  9 15 21 22 27 90 167 214 220 225 227  ...\n *  74 99 133 146 161 166 202 205 245 262 ...\n *  43 83 94 120 125 183 195 206 244 254  ...\n *  1 13 54 91 92 93 106 140 156 194 208  ...\n *  10 39 67 69 131 144 145 154 168 258   ...\n *  6 52 66 113 118 122 139 147 212 213   ...\n *  8 127 150 182 203 204 249 367 400 432 ...\n *  63 65 101 107 108 136 169 170 171 173 ...\n *  55 71 102 155 159 198 228 252 325 419 ...\n *  4 25 34 58 70 152 172 196 199 210 226 ...\n *  2 44 50 88 109 138 141 178 197 211    ...\n *  57 89 129 162 174 179 188 209 238 276 ...\n *  33 41 49 119 126 132 148 181 215 221  ...\n *  3 18 23 26 35 64 105 124 157 186 251  ...\n *  5 16 17 20 31 47 81 98 158 180 187    ...\n *  24 29 51 59 75 82 100 114 117 134 151 ...\n *  30 45 53 60 72 85 111 130 137 142 163 ...\n *  19 37 62 77 79 110 153 352 353 361    ...\n *  0 68 86 123 165 176 193 239 289 336   ...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code KosarajuSharirSCC} class represents a data type for\n *  determining the strong components in a digraph.\n *  The <em>id</em> operation determines in which strong component\n *  a given vertex lies; the <em>areStronglyConnected</em> operation\n *  determines whether two vertices are in the same strong component;\n *  and the <em>count</em> operation determines the number of strong\n *  components.\n *  <p>\n *  The <em>component identifier</em> of a vertex is an integer between\n *  0 and <em>k</em>–1, where <em>k</em> is the number of strong components.\n *  Two vertices have the same component identifier if and only if they\n *  are in the same strong component.\n *  <p>\n *  This implementation uses the Kosaraju-Sharir algorithm.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time,\n *  where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  For alternative implementations of the same API, see\n *  {@link TarjanSCC} and {@link GabowSCC}.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class KosarajuSharirSCC {\n    private boolean[] marked;     // marked[v] = has vertex v been visited?\n    private int[] id;             // id[v] = id of strong component containing v\n    private int count;            // number of strongly-connected components\n\n    /**\n     * Computes the strong components of a digraph.\n     * @param digraph the digraph\n     */\n    public KosarajuSharirSCC(Digraph digraph) {\n\n        // compute reverse postorder of reverse graph\n        DepthFirstOrder dfs = new DepthFirstOrder(digraph.reverse());\n\n        // run DFS on digraph, using reverse postorder to guide calculation\n        marked = new boolean[digraph.V()];\n        id = new int[digraph.V()];\n        for (int v : dfs.reversePost()) {\n            if (!marked[v]) {\n                dfs(digraph, v);\n                count++;\n            }\n        }\n\n        // check that id[] gives strong components\n        assert check(digraph);\n    }\n\n    // DFS on digraph\n    private void dfs(Digraph digraph, int v) {\n        marked[v] = true;\n        id[v] = count;\n        for (int w : digraph.adj(v)) {\n            if (!marked[w]) dfs(digraph, w);\n        }\n    }\n\n    /**\n     * Returns the number of strong components.\n     * @return the number of strong components\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Are vertices {@code v} and {@code w} in the same strong component?\n     * @param  v one vertex\n     * @param  w the other vertex\n     * @return {@code true} if vertices {@code v} and {@code w} are in the same\n     *         strong component, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws IllegalArgumentException unless {@code 0 <= w < V}\n     */\n    public boolean stronglyConnected(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        return id[v] == id[w];\n    }\n\n    /**\n     * Returns the component id of the strong component containing vertex {@code v}.\n     * @param  v the vertex\n     * @return the component id of the strong component containing vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public int id(int v) {\n        validateVertex(v);\n        return id[v];\n    }\n\n    // does the id[] array contain the strongly connected components?\n    private boolean check(Digraph digraph) {\n        TransitiveClosure tc = new TransitiveClosure(digraph);\n        for (int v = 0; v < digraph.V(); v++) {\n            for (int w = 0; w < digraph.V(); w++) {\n                if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v)))\n                    return false;\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code KosarajuSharirSCC} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n        KosarajuSharirSCC scc = new KosarajuSharirSCC(digraph);\n\n        // number of connected components\n        int m = scc.count();\n        StdOut.println(m + \" strong components\");\n\n        // compute list of vertices in each strong component\n        Queue<Integer>[] components = (Queue<Integer>[]) new Queue[m];\n        for (int i = 0; i < m; i++) {\n            components[i] = new Queue<Integer>();\n        }\n        for (int v = 0; v < digraph.V(); v++) {\n            components[scc.id(v)].enqueue(v);\n        }\n\n        // print results\n        for (int i = 0; i < m; i++) {\n            for (int v : components[i]) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/KruskalMST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac KruskalMST.java\n *  Execution:    java  KruskalMST filename.txt\n *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java MinPQ.java\n *                UF.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt\n *\n *  Compute a minimum spanning forest using Kruskal's algorithm.\n *\n *  %  java KruskalMST tinyEWG.txt\n *  0-7 0.16000\n *  2-3 0.17000\n *  1-7 0.19000\n *  0-2 0.26000\n *  5-7 0.28000\n *  4-5 0.35000\n *  6-2 0.40000\n *  1.81000\n *\n *  % java KruskalMST mediumEWG.txt\n *  168-231 0.00268\n *  151-208 0.00391\n *  7-157   0.00516\n *  122-205 0.00647\n *  8-152   0.00702\n *  156-219 0.00745\n *  28-198  0.00775\n *  38-126  0.00845\n *  10-123  0.00886\n *  ...\n *  10.46351\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n *  The {@code KruskalMST} class represents a data type for computing a\n *  <em>minimum spanning tree</em> in an edge-weighted graph.\n *  The edge weights can be positive, zero, or negative and need not\n *  be distinct. If the graph is not connected, it computes a <em>minimum\n *  spanning forest</em>, which is the union of minimum spanning trees\n *  in each connected component. The {@code weight()} method returns the\n *  weight of a minimum spanning tree and the {@code edges()} method\n *  returns its edges.\n *  <p>\n *  This implementation uses <em>Kruskal's algorithm</em> and the\n *  union-find data type.\n *  The constructor takes &Theta;(<em>E</em> log <em>E</em>) time in\n *  the worst case.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>E</em>) extra space (not including the graph).\n *  <p>\n *  This {@code weight()} method correctly computes the weight of the MST\n *  if all arithmetic performed is without floating-point rounding error\n *  or arithmetic overflow.\n *  This is the case if all edge weights are non-negative integers\n *  and the weight of the MST does not exceed 2<sup>52</sup>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/43mst\">Section 4.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For alternate implementations, see {@link LazyPrimMST}, {@link PrimMST},\n *  and {@link BoruvkaMST}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class KruskalMST {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-12;\n\n    private double weight;                        // weight of MST\n    private Queue<Edge> mst = new Queue<Edge>();  // edges in MST\n\n    /**\n     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.\n     * @param graph the edge-weighted graph\n     */\n    public KruskalMST(EdgeWeightedGraph graph) {\n\n        // create array of edges, sorted by weight\n        Edge[] edges = new Edge[graph.E()];\n        int t = 0;\n        for (Edge e: graph.edges()) {\n            edges[t++] = e;\n        }\n        Arrays.sort(edges);\n\n        // run greedy algorithm\n        UF uf = new UF(graph.V());\n        for (int i = 0; i < graph.E() && mst.size() < graph.V() - 1; i++) {\n            Edge e = edges[i];\n            int v = e.either();\n            int w = e.other(v);\n\n            // v-w does not create a cycle\n            if (uf.find(v) != uf.find(w)) {\n                uf.union(v, w);     // merge v and w components\n                mst.enqueue(e);     // add edge e to mst\n                weight += e.weight();\n            }\n        }\n\n        // check optimality conditions\n        assert check(graph);\n    }\n\n    /**\n     * Returns the edges in a minimum spanning tree (or forest).\n     * @return the edges in a minimum spanning tree (or forest) as\n     *    an iterable of edges\n     */\n    public Iterable<Edge> edges() {\n        return mst;\n    }\n\n    /**\n     * Returns the sum of the edge weights in a minimum spanning tree (or forest).\n     * @return the sum of the edge weights in a minimum spanning tree (or forest)\n     */\n    public double weight() {\n        return weight;\n    }\n\n    // check optimality conditions (takes time proportional to E V lg* V)\n    private boolean check(EdgeWeightedGraph graph) {\n\n        // check total weight\n        double total = 0.0;\n        for (Edge e : edges()) {\n            total += e.weight();\n        }\n        if (Math.abs(total - weight()) > FLOATING_POINT_EPSILON) {\n            System.err.printf(\"Weight of edges does not equal weight(): %f vs. %f\\n\", total, weight());\n            return false;\n        }\n\n        // check that it is acyclic\n        UF uf = new UF(graph.V());\n        for (Edge e : edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) == uf.find(w)) {\n                System.err.println(\"Not a forest\");\n                return false;\n            }\n            uf.union(v, w);\n        }\n\n        // check that it is a spanning forest\n        for (Edge e : graph.edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) != uf.find(w)) {\n                System.err.println(\"Not a spanning forest\");\n                return false;\n            }\n        }\n\n        // check that it is a minimal spanning forest (cut optimality conditions)\n        for (Edge e : edges()) {\n\n            // all edges in MST except e\n            uf = new UF(graph.V());\n            for (Edge f : mst) {\n                int x = f.either(), y = f.other(x);\n                if (f != e) uf.union(x, y);\n            }\n\n            // check that e is min weight edge in crossing cut\n            for (Edge f : graph.edges()) {\n                int x = f.either(), y = f.other(x);\n                if (uf.find(x) != uf.find(y)) {\n                    if (f.weight() < e.weight()) {\n                        System.err.println(\"Edge \" + f + \" violates cut optimality conditions\");\n                        return false;\n                    }\n                }\n            }\n\n        }\n\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code KruskalMST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph G = new EdgeWeightedGraph(in);\n        KruskalMST mst = new KruskalMST(G);\n        for (Edge e : mst.edges()) {\n            StdOut.println(e);\n        }\n        StdOut.printf(\"%.5f\\n\", mst.weight());\n    }\n\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LSD.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LSD.java\n *  Execution:    java LSD < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/51radix/words3.txt\n *\n *  LSD radix sort\n *\n *    - Sort a String[] array of n extended ASCII strings (R = 256), each of length w.\n *\n *    - Sort an int[] array of n 32-bit integers, treating each integer as\n *      a sequence of w = 4 bytes (R = 256).\n *\n *  Uses extra space proportional to n + R.\n *\n *\n *  % java LSD < words3.txt\n *  all\n *  bad\n *  bed\n *  bug\n *  dad\n *  ...\n *  yes\n *  yet\n *  zoo\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LSD} class provides static methods for sorting an\n *  array of <em>w</em>-character strings or 32-bit integers using LSD radix sort.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/51radix\">Section 5.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LSD {\n    private static final int BITS_PER_BYTE = 8;\n\n    // do not instantiate\n    private LSD() { }\n\n   /**\n     * Rearranges the array of w-character strings in ascending order.\n     *\n     * @param a the array to be sorted\n     * @param w the number of characters per string\n     */\n    public static void sort(String[] a, int w) {\n        int n = a.length;\n        int R = 256;   // extend ASCII alphabet size\n        String[] aux = new String[n];\n\n        for (int d = w-1; d >= 0; d--) {\n            // sort by key-indexed counting on dth character\n\n            // compute frequency counts\n            int[] count = new int[R+1];\n            for (int i = 0; i < n; i++)\n                count[a[i].charAt(d) + 1]++;\n\n            // compute cumulates\n            for (int r = 0; r < R; r++)\n                count[r+1] += count[r];\n\n            // move data\n            for (int i = 0; i < n; i++)\n                aux[count[a[i].charAt(d)]++] = a[i];\n\n            // copy back\n            for (int i = 0; i < n; i++)\n                a[i] = aux[i];\n        }\n    }\n\n   /**\n     * Rearranges the array of 32-bit integers in ascending order.\n     * This is about 2-5x faster than Arrays.sort().\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(int[] a) {\n        final int BITS = 32;                 // each int is 32 bits\n        final int R = 1 << BITS_PER_BYTE;    // each byte is between 0 and 255\n        final int MASK = R - 1;              // 0xFF\n        final int w = BITS / BITS_PER_BYTE;  // each int is 4 bytes\n\n        int n = a.length;\n        int[] aux = new int[n];\n\n        for (int d = 0; d < w; d++) {\n\n            // compute frequency counts\n            int[] count = new int[R+1];\n            for (int i = 0; i < n; i++) {\n                int c = (a[i] >> BITS_PER_BYTE*d) & MASK;\n                count[c + 1]++;\n            }\n\n            // compute cumulates\n            for (int r = 0; r < R; r++)\n                count[r+1] += count[r];\n\n            // for most significant byte, 0x80-0xFF comes before 0x00-0x7F\n            if (d == w-1) {\n                int shift1 = count[R] - count[R/2];\n                int shift2 = count[R/2];\n                for (int r = 0; r < R/2; r++)\n                    count[r] += shift1;\n                for (int r = R/2; r < R; r++)\n                    count[r] -= shift2;\n            }\n\n            // move data\n            for (int i = 0; i < n; i++) {\n                int c = (a[i] >> BITS_PER_BYTE*d) & MASK;\n                aux[count[c]++] = a[i];\n            }\n\n            // optimization: swap a[] and aux[] references instead of copying\n            // (since w is even, the argument a[] to sort() will be the array\n            // with the sorted integers)\n            int[] temp = a;\n            a = aux;\n            aux = temp;\n        }\n    }\n\n\n    /**\n     * Reads in a sequence of fixed-length strings from standard input;\n     * LSD radix sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        int n = a.length;\n\n        // check that strings have fixed length\n        int w = a[0].length();\n        for (int i = 0; i < n; i++)\n            assert a[i].length() == w : \"Strings must have fixed length\";\n\n        // sort the strings\n        sort(a, w);\n\n        // print results\n        for (int i = 0; i < n; i++)\n            StdOut.println(a[i]);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LZW.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LZW.java\n *  Execution:    java LZW - < input.txt   (compress)\n *  Execution:    java LZW + < input.txt   (expand)\n *  Dependencies: BinaryIn.java BinaryOut.java\n *  Data files:   https://algs4.cs.princeton.edu/55compression/abraLZW.txt\n *                https://algs4.cs.princeton.edu/55compression/ababLZW.txt\n *\n *  Compress or expand binary input from standard input using LZW.\n *\n\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LZW} class provides static methods for compressing\n *  and expanding a binary input using LZW compression over the 8-bit extended\n *  ASCII alphabet with 12-bit codewords.\n *  <p>\n *  WARNING: Starting with Oracle Java 7u6, the substring method takes time and\n *  space linear in the length of the extracted substring (instead of constant\n *  time an space as in earlier versions). As a result, compression takes\n *  quadratic time. TODO: fix.\n *  See <a href = \"http://java-performance.info/changes-to-string-java-1-7-0_06/\">this article</a>\n *  for more details.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LZW {\n    private static final int R = 256;        // number of input chars\n    private static final int L = 4096;       // number of codewords = 2^W\n    private static final int W = 12;         // codeword width\n\n    // Do not instantiate.\n    private LZW() { }\n\n    /**\n     * Reads a sequence of 8-bit bytes from standard input; compresses\n     * them using LZW compression with 12-bit codewords; and writes the results\n     * to standard output.\n     */\n    public static void compress() {\n        String input = BinaryStdIn.readString();\n        TST<Integer> st = new TST<Integer>();\n\n        // since TST is not balanced, it would be better to insert in a different order\n        for (int i = 0; i < R; i++)\n            st.put(\"\" + (char) i, i);\n\n        int code = R+1;  // R is codeword for EOF\n\n        while (input.length() > 0) {\n            String s = st.longestPrefixOf(input);  // Find max prefix match s.\n            BinaryStdOut.write(st.get(s), W);      // Print s's encoding.\n            int t = s.length();\n            if (t < input.length() && code < L)    // Add s to symbol table.\n                st.put(input.substring(0, t + 1), code++);\n            input = input.substring(t);            // Scan past s in input.\n        }\n        BinaryStdOut.write(R, W);\n        BinaryStdOut.close();\n    }\n\n    /**\n     * Reads a sequence of bit encoded using LZW compression with\n     * 12-bit codewords from standard input; expands them; and writes\n     * the results to standard output.\n     */\n    public static void expand() {\n        String[] st = new String[L];\n        int i; // next available codeword value\n\n        // initialize symbol table with all 1-character strings\n        for (i = 0; i < R; i++)\n            st[i] = \"\" + (char) i;\n        st[i++] = \"\";                        // (unused) lookahead for EOF\n\n        int codeword = BinaryStdIn.readInt(W);\n        if (codeword == R) return;           // expanded message is empty string\n        String val = st[codeword];\n\n        while (true) {\n            BinaryStdOut.write(val);\n            codeword = BinaryStdIn.readInt(W);\n            if (codeword == R) break;\n            String s = st[codeword];\n            if (i == codeword) s = val + val.charAt(0);   // special case hack\n            if (i < L) st[i++] = val + s.charAt(0);\n            val = s;\n        }\n        BinaryStdOut.close();\n    }\n\n    /**\n     * Sample client that calls {@code compress()} if the command-line\n     * argument is \"-\" an {@code expand()} if it is \"+\".\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        if      (args[0].equals(\"-\")) compress();\n        else if (args[0].equals(\"+\")) expand();\n        else throw new IllegalArgumentException(\"Illegal command line argument\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LazyPrimMST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LazyPrimMST.java\n *  Execution:    java LazyPrimMST filename.txt\n *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java\n *                MinPQ.java UF.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt\n *\n *  Compute a minimum spanning forest using a lazy version of Prim's\n *  algorithm.\n *\n *  %  java LazyPrimMST tinyEWG.txt\n *  0-7 0.16000\n *  1-7 0.19000\n *  0-2 0.26000\n *  2-3 0.17000\n *  5-7 0.28000\n *  4-5 0.35000\n *  6-2 0.40000\n *  1.81000\n *\n *  % java LazyPrimMST mediumEWG.txt\n *  0-225   0.02383\n *  49-225  0.03314\n *  44-49   0.02107\n *  44-204  0.01774\n *  49-97   0.03121\n *  202-204 0.04207\n *  176-202 0.04299\n *  176-191 0.02089\n *  68-176  0.04396\n *  58-68   0.04795\n *  10.46351\n *\n *  % java LazyPrimMST largeEWG.txt\n *  ...\n *  647.66307\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LazyPrimMST} class represents a data type for computing a\n *  <em>minimum spanning tree</em> in an edge-weighted graph.\n *  The edge weights can be positive, zero, or negative and need not\n *  be distinct. If the graph is not connected, it computes a <em>minimum\n *  spanning forest</em>, which is the union of minimum spanning trees\n *  in each connected component. The {@code weight()} method returns the\n *  weight of a minimum spanning tree and the {@code edges()} method\n *  returns its edges.\n *  <p>\n *  This implementation uses a lazy version of <em>Prim's algorithm</em>\n *  with a binary heap of edges.\n *  The constructor takes &Theta;(<em>E</em> log <em>E</em>) time in\n *  the worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>E</em>) extra space in the worst case\n *  (not including the edge-weighted graph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/43mst\">Section 4.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For alternate implementations, see {@link PrimMST}, {@link KruskalMST},\n *  and {@link BoruvkaMST}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LazyPrimMST {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-12;\n\n    private double weight;       // total weight of MST\n    private Queue<Edge> mst;     // edges in the MST\n    private boolean[] marked;    // marked[v] = true iff v on tree\n    private MinPQ<Edge> pq;      // edges with one endpoint in tree\n\n    /**\n     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.\n     * @param G the edge-weighted graph\n     */\n    public LazyPrimMST(EdgeWeightedGraph G) {\n        mst = new Queue<Edge>();\n        pq = new MinPQ<Edge>();\n        marked = new boolean[G.V()];\n        for (int v = 0; v < G.V(); v++)     // run Prim from all vertices to\n            if (!marked[v]) prim(G, v);     // get a minimum spanning forest\n\n        // check optimality conditions\n        assert check(G);\n    }\n\n    // run Prim's algorithm\n    private void prim(EdgeWeightedGraph G, int s) {\n        scan(G, s);\n        while (!pq.isEmpty()) {                        // better to stop when mst has V-1 edges\n            Edge e = pq.delMin();                      // smallest edge on pq\n            int v = e.either(), w = e.other(v);        // two endpoints\n            assert marked[v] || marked[w];\n            if (marked[v] && marked[w]) continue;      // lazy, both v and w already scanned\n            mst.enqueue(e);                            // add e to MST\n            weight += e.weight();\n            if (!marked[v]) scan(G, v);               // v becomes part of tree\n            if (!marked[w]) scan(G, w);               // w becomes part of tree\n        }\n    }\n\n    // add all edges e incident to v onto pq if the other endpoint has not yet been scanned\n    private void scan(EdgeWeightedGraph G, int v) {\n        assert !marked[v];\n        marked[v] = true;\n        for (Edge e : G.adj(v))\n            if (!marked[e.other(v)]) pq.insert(e);\n    }\n\n    /**\n     * Returns the edges in a minimum spanning tree (or forest).\n     * @return the edges in a minimum spanning tree (or forest) as\n     *    an iterable of edges\n     */\n    public Iterable<Edge> edges() {\n        return mst;\n    }\n\n    /**\n     * Returns the sum of the edge weights in a minimum spanning tree (or forest).\n     * @return the sum of the edge weights in a minimum spanning tree (or forest)\n     */\n    public double weight() {\n        return weight;\n    }\n\n    // check optimality conditions (takes time proportional to E V lg* V)\n    private boolean check(EdgeWeightedGraph G) {\n\n        // check weight\n        double totalWeight = 0.0;\n        for (Edge e : edges()) {\n            totalWeight += e.weight();\n        }\n        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {\n            System.err.printf(\"Weight of edges does not equal weight(): %f vs. %f\\n\", totalWeight, weight());\n            return false;\n        }\n\n        // check that it is acyclic\n        UF uf = new UF(G.V());\n        for (Edge e : edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) == uf.find(w)) {\n                System.err.println(\"Not a forest\");\n                return false;\n            }\n            uf.union(v, w);\n        }\n\n        // check that it is a spanning forest\n        for (Edge e : G.edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) != uf.find(w)) {\n                System.err.println(\"Not a spanning forest\");\n                return false;\n            }\n        }\n\n        // check that it is a minimal spanning forest (cut optimality conditions)\n        for (Edge e : edges()) {\n\n            // all edges in MST except e\n            uf = new UF(G.V());\n            for (Edge f : mst) {\n                int x = f.either(), y = f.other(x);\n                if (f != e) uf.union(x, y);\n            }\n\n            // check that e is min weight edge in crossing cut\n            for (Edge f : G.edges()) {\n                int x = f.either(), y = f.other(x);\n                if (uf.find(x) != uf.find(y)) {\n                    if (f.weight() < e.weight()) {\n                        System.err.println(\"Edge \" + f + \" violates cut optimality conditions\");\n                        return false;\n                    }\n                }\n            }\n\n        }\n\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code LazyPrimMST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph G = new EdgeWeightedGraph(in);\n        LazyPrimMST mst = new LazyPrimMST(G);\n        for (Edge e : mst.edges()) {\n            StdOut.println(e);\n        }\n        StdOut.printf(\"%.5f\\n\", mst.weight());\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LinearProbingHashST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LinearProbingHashST.java\n *  Execution:    java LinearProbingHashST < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/34hash/tinyST.txt\n *\n *  Symbol-table implementation with linear-probing hash table.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LinearProbingHashST} class represents a symbol table of generic\n *  key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  This implementation uses a linear probing hash table. It requires that\n *  the key type overrides the {@code equals()} and {@code hashCode()} methods.\n *  The expected time per <em>put</em>, <em>contains</em>, or <em>remove</em>\n *  operation is constant, subject to the uniform hashing assumption.\n *  The <em>size</em>, and <em>is-empty</em> operations take constant time.\n *  Construction takes constant time.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/34hash\">Section 3.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For other implementations, see {@link ST}, {@link BinarySearchST},\n *  {@link SequentialSearchST}, {@link BST}, {@link RedBlackBST}, and\n *  {@link SeparateChainingHashST},\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LinearProbingHashST<Key, Value> {\n\n    // must be a power of 2\n    private static final int INIT_CAPACITY = 4;\n\n    private int n;           // number of key-value pairs in the symbol table\n    private int m;           // size of linear probing table\n    private Key[] keys;      // the keys\n    private Value[] vals;    // the values\n\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public LinearProbingHashST() {\n        this(INIT_CAPACITY);\n    }\n\n    /**\n     * Initializes an empty symbol table with the specified initial capacity.\n     *\n     * @param capacity the initial capacity\n     */\n    public LinearProbingHashST(int capacity) {\n        m = capacity;\n        n = 0;\n        keys = (Key[])   new Object[m];\n        vals = (Value[]) new Object[m];\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     *\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     *\n     * @return {@code true} if this symbol table is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns true if this symbol table contains the specified key.\n     *\n     * @param  key the key\n     * @return {@code true} if this symbol table contains {@code key};\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        return get(key) != null;\n    }\n\n    // hash function for keys - returns value between 0 and m-1\n    private int hashTextbook(Key key) {\n        return (key.hashCode() & 0x7fffffff) % m;\n    }\n\n    // hash function for keys - returns value between 0 and m-1 (assumes m is a power of 2)\n    // (from Java 7 implementation, protects against poor quality hashCode() implementations)\n    private int hash(Key key) {\n        int h = key.hashCode();\n        h ^= (h >>> 20) ^ (h >>> 12) ^ (h >>> 7) ^ (h >>> 4);\n        return h & (m-1);\n    }\n\n    // resizes the hash table to the given capacity by re-hashing all of the keys\n    private void resize(int capacity) {\n        LinearProbingHashST<Key, Value> temp = new LinearProbingHashST<Key, Value>(capacity);\n        for (int i = 0; i < m; i++) {\n            if (keys[i] != null) {\n                temp.put(keys[i], vals[i]);\n            }\n        }\n        keys = temp.keys;\n        vals = temp.vals;\n        m    = temp.m;\n    }\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n\n        if (val == null) {\n            delete(key);\n            return;\n        }\n\n        // double table size if 50% full\n        if (n >= m/2) resize(2*m);\n\n        int i;\n        for (i = hash(key); keys[i] != null; i = (i + 1) % m) {\n            if (keys[i].equals(key)) {\n                vals[i] = val;\n                return;\n            }\n        }\n        keys[i] = key;\n        vals[i] = val;\n        n++;\n    }\n\n    /**\n     * Returns the value associated with the specified key.\n     * @param key the key\n     * @return the value associated with {@code key};\n     *         {@code null} if no such value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        for (int i = hash(key); keys[i] != null; i = (i + 1) % m)\n            if (keys[i].equals(key))\n                return vals[i];\n        return null;\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        if (!contains(key)) return;\n\n        // find position i of key\n        int i = hash(key);\n        while (!key.equals(keys[i])) {\n            i = (i + 1) % m;\n        }\n\n        // delete key and associated value\n        keys[i] = null;\n        vals[i] = null;\n\n        // rehash all keys in same cluster\n        i = (i + 1) % m;\n        while (keys[i] != null) {\n            // delete keys[i] and vals[i] and reinsert\n            Key   keyToRehash = keys[i];\n            Value valToRehash = vals[i];\n            keys[i] = null;\n            vals[i] = null;\n            n--;\n            put(keyToRehash, valToRehash);\n            i = (i + 1) % m;\n        }\n\n        n--;\n\n        // halves size of array if it's 12.5% full or less\n        if (n > 0 && n <= m/8) resize(m/2);\n\n        assert check();\n    }\n\n    /**\n     * Returns all keys in this symbol table as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     *\n     * @return all keys in this symbol table\n     */\n    public Iterable<Key> keys() {\n        Queue<Key> queue = new Queue<Key>();\n        for (int i = 0; i < m; i++)\n            if (keys[i] != null) queue.enqueue(keys[i]);\n        return queue;\n    }\n\n    // integrity check - don't check after each put() because\n    // integrity not maintained during a call to delete()\n    private boolean check() {\n\n        // check that hash table is at most 50% full\n        if (m < 2*n) {\n            System.err.println(\"Hash table size m = \" + m + \"; array size n = \" + n);\n            return false;\n        }\n\n        // check that each key in table can be found by get()\n        for (int i = 0; i < m; i++) {\n            if (keys[i] == null) continue;\n            else if (get(keys[i]) != vals[i]) {\n                System.err.println(\"get[\" + keys[i] + \"] = \" + get(keys[i]) + \"; vals[i] = \" + vals[i]);\n                return false;\n            }\n        }\n        return true;\n    }\n\n\n    /**\n     * Unit tests the {@code LinearProbingHashST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        LinearProbingHashST<String, Integer> st = new LinearProbingHashST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n\n        // print keys\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LinearProgramming.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LinearProgramming.java\n *  Execution:    java LinearProgramming m n\n *  Dependencies: StdOut.java\n *\n *  Given an m-by-n matrix A, an m-length vector b, and an\n *  n-length vector c, solve the  LP { max cx : Ax <= b, x >= 0 }.\n *  Assumes that b >= 0 so that x = 0 is a basic feasible solution.\n *\n *  Creates an (m+1)-by-(n+m+1) simplex tableaux with the\n *  RHS in column m+n, the objective function in row m, and\n *  slack variables in columns m through m+n-1.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LinearProgramming} class represents a data type for solving a\n *  linear program of the form { max cx : Ax &le; b, x &ge; 0 }, where A is an\n *  m-by-n matrix, b is an m-length vector, and c is an n-length vector.\n *  For simplicity, we assume that A is of full rank and that b &ge; 0\n *  so that x = 0 is a basic feasible solution.\n *  <p>\n *  The data type supplies methods for determining the optimal primal and\n *  dual solutions.\n *  <p>\n *  This is a bare-bones implementation of the <em>simplex algorithm</em>.\n *  It uses Bland's rule to determine the entering and leaving variables.\n *  It is not suitable for use on large inputs.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without floating-point rounding error or arithmetic overflow.\n *  In practice, there will be floating-point rounding error\n *  and this implementation is not robust in the presence of\n *  such errors.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/65reductions\">Section 6.5</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LinearProgramming {\n    private static final double EPSILON = 1.0E-10;\n    private double[][] a;   // tableaux\n    private int m;          // number of constraints\n    private int n;          // number of original variables\n\n    private int[] basis;    // basis[i] = basic variable corresponding to row i\n                            // only needed to print out solution, not book\n\n    /**\n     * Determines an optimal solution to the linear program\n     * { max cx : Ax &le; b, x &ge; 0 }, where A is an m-by-n\n     * matrix, b is an m-length vector, and c is an n-length vector.\n     *\n     * @param  A the <em>m</em>-by-<em>b</em> matrix\n     * @param  b the <em>m</em>-length RHS vector\n     * @param  c the <em>n</em>-length cost vector\n     * @throws IllegalArgumentException unless {@code b[i] >= 0} for each {@code i}\n     * @throws ArithmeticException if the linear program is unbounded\n     */\n    public LinearProgramming(double[][] A, double[] b, double[] c) {\n        m = b.length;\n        n = c.length;\n        for (int i = 0; i < m; i++)\n            if (!(b[i] >= 0)) throw new IllegalArgumentException(\"RHS must be nonnegative\");\n\n        a = new double[m+1][n+m+1];\n        for (int i = 0; i < m; i++)\n            for (int j = 0; j < n; j++)\n                a[i][j] = A[i][j];\n        for (int i = 0; i < m; i++)\n            a[i][n+i] = 1.0;\n        for (int j = 0; j < n; j++)\n            a[m][j] = c[j];\n        for (int i = 0; i < m; i++)\n            a[i][m+n] = b[i];\n\n        basis = new int[m];\n        for (int i = 0; i < m; i++)\n            basis[i] = n + i;\n\n        solve();\n\n        // check optimality conditions\n        assert check(A, b, c);\n    }\n\n    // run simplex algorithm starting from initial BFS\n    private void solve() {\n        while (true) {\n\n            // find entering column q\n            int q = bland();\n            if (q == -1) break;  // optimal\n\n            // find leaving row p\n            int p = minRatioRule(q);\n            if (p == -1) throw new ArithmeticException(\"Linear program is unbounded\");\n\n            // pivot\n            pivot(p, q);\n\n            // update basis\n            basis[p] = q;\n        }\n    }\n\n    // lowest index of a non-basic column with a positive cost\n    private int bland() {\n        for (int j = 0; j < m+n; j++)\n            if (a[m][j] > 0) return j;\n        return -1;  // optimal\n    }\n\n   // index of a non-basic column with most positive cost\n    private int dantzig() {\n        int q = 0;\n        for (int j = 1; j < m+n; j++)\n            if (a[m][j] > a[m][q]) q = j;\n\n        if (a[m][q] <= 0) return -1;  // optimal\n        else return q;\n    }\n\n    // find row p using min ratio rule (-1 if no such row)\n    // (smallest such index if there is a tie)\n    private int minRatioRule(int q) {\n        int p = -1;\n        for (int i = 0; i < m; i++) {\n            // if (a[i][q] <= 0) continue;\n            if (a[i][q] <= EPSILON) continue;\n            else if (p == -1) p = i;\n            else if ((a[i][m+n] / a[i][q]) < (a[p][m+n] / a[p][q])) p = i;\n        }\n        return p;\n    }\n\n    // pivot on entry (p, q) using Gauss-Jordan elimination\n    private void pivot(int p, int q) {\n\n        // everything but row p and column q\n        for (int i = 0; i <= m; i++)\n            for (int j = 0; j <= m+n; j++)\n                if (i != p && j != q) a[i][j] -= a[p][j] * (a[i][q] / a[p][q]);\n\n        // zero out column q\n        for (int i = 0; i <= m; i++)\n            if (i != p) a[i][q] = 0.0;\n\n        // scale row p\n        for (int j = 0; j <= m+n; j++)\n            if (j != q) a[p][j] /= a[p][q];\n        a[p][q] = 1.0;\n    }\n\n    /**\n     * Returns the optimal value of this linear program.\n     *\n     * @return the optimal value of this linear program\n     *\n     */\n    public double value() {\n        return -a[m][m+n];\n    }\n\n    /**\n     * Returns the optimal primal solution to this linear program.\n     *\n     * @return the optimal primal solution to this linear program\n     */\n    public double[] primal() {\n        double[] x = new double[n];\n        for (int i = 0; i < m; i++)\n            if (basis[i] < n) x[basis[i]] = a[i][m+n];\n        return x;\n    }\n\n    /**\n     * Returns the optimal dual solution to this linear program\n     *\n     * @return the optimal dual solution to this linear program\n     */\n    public double[] dual() {\n        double[] y = new double[m];\n        for (int i = 0; i < m; i++) {\n            y[i] = -a[m][n+i];\n            if (y[i] == -0.0) y[i] = 0.0;\n        }\n        return y;\n    }\n\n\n    // is the solution primal feasible?\n    private boolean isPrimalFeasible(double[][] A, double[] b) {\n        double[] x = primal();\n\n        // check that x >= 0\n        for (int j = 0; j < x.length; j++) {\n            if (x[j] < -EPSILON) {\n                StdOut.println(\"x[\" + j + \"] = \" + x[j] + \" is negative\");\n                return false;\n            }\n        }\n\n        // check that Ax <= b\n        for (int i = 0; i < m; i++) {\n            double sum = 0.0;\n            for (int j = 0; j < n; j++) {\n                sum += A[i][j] * x[j];\n            }\n            if (sum > b[i] + EPSILON) {\n                StdOut.println(\"not primal feasible\");\n                StdOut.println(\"b[\" + i + \"] = \" + b[i] + \", sum = \" + sum);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // is the solution dual feasible?\n    private boolean isDualFeasible(double[][] A, double[] c) {\n        double[] y = dual();\n\n        // check that y >= 0\n        for (int i = 0; i < y.length; i++) {\n            if (y[i] < -EPSILON) {\n                StdOut.println(\"y[\" + i + \"] = \" + y[i] + \" is negative\");\n                return false;\n            }\n        }\n\n        // check that yA >= c\n        for (int j = 0; j < n; j++) {\n            double sum = 0.0;\n            for (int i = 0; i < m; i++) {\n                sum += A[i][j] * y[i];\n            }\n            if (sum < c[j] - EPSILON) {\n                StdOut.println(\"not dual feasible\");\n                StdOut.println(\"c[\" + j + \"] = \" + c[j] + \", sum = \" + sum);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // check that optimal value = cx = yb\n    private boolean isOptimal(double[] b, double[] c) {\n        double[] x = primal();\n        double[] y = dual();\n        double value = value();\n\n        // check that value = cx = yb\n        double value1 = 0.0;\n        for (int j = 0; j < x.length; j++)\n            value1 += c[j] * x[j];\n        double value2 = 0.0;\n        for (int i = 0; i < y.length; i++)\n            value2 += y[i] * b[i];\n        if (Math.abs(value - value1) > EPSILON || Math.abs(value - value2) > EPSILON) {\n            StdOut.println(\"value = \" + value + \", cx = \" + value1 + \", yb = \" + value2);\n            return false;\n        }\n\n        return true;\n    }\n\n    private boolean check(double[][]A, double[] b, double[] c) {\n        return isPrimalFeasible(A, b) && isDualFeasible(A, c) && isOptimal(b, c);\n    }\n\n    // print tableaux\n    private void show() {\n        StdOut.println(\"m = \" + m);\n        StdOut.println(\"n = \" + n);\n        for (int i = 0; i <= m; i++) {\n            for (int j = 0; j <= m+n; j++) {\n                StdOut.printf(\"%7.2f \", a[i][j]);\n                // StdOut.printf(\"%10.7f \", a[i][j]);\n            }\n            StdOut.println();\n        }\n        StdOut.println(\"value = \" + value());\n        for (int i = 0; i < m; i++)\n            if (basis[i] < n) StdOut.println(\"x_\" + basis[i] + \" = \" + a[i][m+n]);\n        StdOut.println();\n    }\n\n\n    private static void test(double[][] A, double[] b, double[] c) {\n        LinearProgramming lp;\n        try {\n            lp = new LinearProgramming(A, b, c);\n        }\n        catch (ArithmeticException e) {\n            System.out.println(e);\n            return;\n        }\n\n        StdOut.println(\"value = \" + lp.value());\n        double[] x = lp.primal();\n        for (int i = 0; i < x.length; i++)\n            StdOut.println(\"x[\" + i + \"] = \" + x[i]);\n        double[] y = lp.dual();\n        for (int j = 0; j < y.length; j++)\n            StdOut.println(\"y[\" + j + \"] = \" + y[j]);\n    }\n\n    private static void test1() {\n        double[][] A = {\n            { -1,  1,  0 },\n            {  1,  4,  0 },\n            {  2,  1,  0 },\n            {  3, -4,  0 },\n            {  0,  0,  1 },\n        };\n        double[] c = { 1, 1, 1 };\n        double[] b = { 5, 45, 27, 24, 4 };\n        test(A, b, c);\n    }\n\n\n    // x0 = 12, x1 = 28, opt = 800\n    private static void test2() {\n        double[] c = {  13.0,  23.0 };\n        double[] b = { 480.0, 160.0, 1190.0 };\n        double[][] A = {\n            {  5.0, 15.0 },\n            {  4.0,  4.0 },\n            { 35.0, 20.0 },\n        };\n        test(A, b, c);\n    }\n\n    // unbounded\n    private static void test3() {\n        double[] c = { 2.0, 3.0, -1.0, -12.0 };\n        double[] b = {  3.0,   2.0 };\n        double[][] A = {\n            { -2.0, -9.0,  1.0,  9.0 },\n            {  1.0,  1.0, -1.0, -2.0 },\n        };\n        test(A, b, c);\n    }\n\n    // degenerate - cycles if you choose most positive objective function coefficient\n    private static void test4() {\n        double[] c = { 10.0, -57.0, -9.0, -24.0 };\n        double[] b = {  0.0,   0.0,  1.0 };\n        double[][] A = {\n            { 0.5, -5.5, -2.5, 9.0 },\n            { 0.5, -1.5, -0.5, 1.0 },\n            { 1.0,  0.0,  0.0, 0.0 },\n        };\n        test(A, b, c);\n    }\n\n\n    /**\n     * Unit tests the {@code LinearProgramming} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        StdOut.println(\"----- test 1 --------------------\");\n        test1();\n        StdOut.println();\n\n        StdOut.println(\"----- test 2 --------------------\");\n        test2();\n        StdOut.println();\n\n        StdOut.println(\"----- test 3 --------------------\");\n        test3();\n        StdOut.println();\n\n        StdOut.println(\"----- test 4 --------------------\");\n        test4();\n        StdOut.println();\n\n        StdOut.println(\"----- test random ---------------\");\n        int m = Integer.parseInt(args[0]);\n        int n = Integer.parseInt(args[1]);\n        double[] c = new double[n];\n        double[] b = new double[m];\n        double[][] A = new double[m][n];\n        for (int j = 0; j < n; j++)\n            c[j] = StdRandom.uniformInt(1000);\n        for (int i = 0; i < m; i++)\n            b[i] = StdRandom.uniformInt(1000);\n        for (int i = 0; i < m; i++)\n            for (int j = 0; j < n; j++)\n                A[i][j] = StdRandom.uniformInt(100);\n        LinearProgramming lp = new LinearProgramming(A, b, c);\n        test(A, b, c);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LinearRegression.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LinearRegression.java\n *  Execution:    java  LinearRegression\n *  Dependencies: none\n *\n *  Compute least squares solution to y = beta * x + alpha.\n *  Simple linear regression.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code LinearRegression} class performs a simple linear regression\n *  on an set of <em>n</em> data points (<em>y<sub>i</sub></em>, <em>x<sub>i</sub></em>).\n *  That is, it fits a straight line <em>y</em> = &alpha; + &beta; <em>x</em>,\n *  (where <em>y</em> is the response variable, <em>x</em> is the predictor variable,\n *  &alpha; is the <em>y-intercept</em>, and &beta; is the <em>slope</em>)\n *  that minimizes the sum of squared residuals of the linear regression model.\n *  It also computes associated statistics, including the coefficient of\n *  determination <em>R</em><sup>2</sup> and the standard deviation of the\n *  estimates for the slope and <em>y</em>-intercept.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LinearRegression {\n    private final double intercept, slope;\n    private final double r2;\n    private final double svar0, svar1;\n\n   /**\n     * Performs a linear regression on the data points {@code (y[i], x[i])}.\n     *\n     * @param  x the values of the predictor variable\n     * @param  y the corresponding values of the response variable\n     * @throws IllegalArgumentException if the lengths of the two arrays are not equal\n     */\n    public LinearRegression(double[] x, double[] y) {\n        if (x.length != y.length) {\n            throw new IllegalArgumentException(\"array lengths are not equal\");\n        }\n        int n = x.length;\n\n        // first pass\n        double sumx = 0.0, sumy = 0.0, sumx2 = 0.0;\n        for (int i = 0; i < n; i++) {\n            sumx  += x[i];\n            sumx2 += x[i]*x[i];\n            sumy  += y[i];\n        }\n        double xbar = sumx / n;\n        double ybar = sumy / n;\n\n        // second pass: compute summary statistics\n        double xxbar = 0.0, yybar = 0.0, xybar = 0.0;\n        for (int i = 0; i < n; i++) {\n            xxbar += (x[i] - xbar) * (x[i] - xbar);\n            yybar += (y[i] - ybar) * (y[i] - ybar);\n            xybar += (x[i] - xbar) * (y[i] - ybar);\n        }\n        slope  = xybar / xxbar;\n        intercept = ybar - slope * xbar;\n\n        // more statistical analysis\n        double rss = 0.0;      // residual sum of squares\n        double ssr = 0.0;      // regression sum of squares\n        for (int i = 0; i < n; i++) {\n            double fit = slope*x[i] + intercept;\n            rss += (fit - y[i]) * (fit - y[i]);\n            ssr += (fit - ybar) * (fit - ybar);\n        }\n\n        int degreesOfFreedom = n-2;\n        r2    = ssr / yybar;\n        double svar  = rss / degreesOfFreedom;\n        svar1 = svar / xxbar;\n        svar0 = svar/n + xbar*xbar*svar1;\n    }\n\n   /**\n     * Returns the <em>y</em>-intercept &alpha; of the best of the best-fit line <em>y</em> = &alpha; + &beta; <em>x</em>.\n     *\n     * @return the <em>y</em>-intercept &alpha; of the best-fit line <em>y = &alpha; + &beta; x</em>\n     */\n    public double intercept() {\n        return intercept;\n    }\n\n   /**\n     * Returns the slope &beta; of the best of the best-fit line <em>y</em> = &alpha; + &beta; <em>x</em>.\n     *\n     * @return the slope &beta; of the best-fit line <em>y</em> = &alpha; + &beta; <em>x</em>\n     */\n    public double slope() {\n        return slope;\n    }\n\n   /**\n     * Returns the coefficient of determination <em>R</em><sup>2</sup>.\n     *\n     * @return the coefficient of determination <em>R</em><sup>2</sup>,\n     *         which is a real number between 0 and 1\n     */\n    public double R2() {\n        return r2;\n    }\n\n   /**\n     * Returns the standard error of the estimate for the intercept.\n     *\n     * @return the standard error of the estimate for the intercept\n     */\n    public double interceptStdErr() {\n        return Math.sqrt(svar0);\n    }\n\n   /**\n     * Returns the standard error of the estimate for the slope.\n     *\n     * @return the standard error of the estimate for the slope\n     */\n    public double slopeStdErr() {\n        return Math.sqrt(svar1);\n    }\n\n   /**\n     * Returns the expected response {@code y} given the value of the predictor\n     * variable {@code x}.\n     *\n     * @param  x the value of the predictor variable\n     * @return the expected response {@code y} given the value of the predictor\n     *         variable {@code x}\n     */\n    public double predict(double x) {\n        return slope*x + intercept;\n    }\n\n   /**\n     * Returns a string representation of the simple linear regression model.\n     *\n     * @return a string representation of the simple linear regression model,\n     *         including the best-fit line and the coefficient of determination\n     *         <em>R</em><sup>2</sup>\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        s.append(String.format(\"%.2f n + %.2f\", slope(), intercept()));\n        s.append(\"  (R^2 = \" + String.format(\"%.3f\", R2()) + \")\");\n        return s.toString();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LinkedBag.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LinkedBag.java\n *  Execution:    java LinkedBag < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *\n *  A generic bag or multiset, implemented using a singly linked list.\n *\n *  % more tobe.txt\n *  to be or not to - be - - that - - - is\n *\n *  % java LinkedBag < tobe.txt\n *  size of bag = 14\n *  is\n *  -\n *  -\n *  -\n *  that\n *  -\n *  -\n *  be\n *  -\n *  to\n *  not\n *  or\n *  be\n *  to\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code LinkedBag} class represents a bag (or multiset) of\n *  generic items. It supports insertion and iterating over the\n *  items in arbitrary order.\n *  <p>\n *  This implementation uses a singly linked list with a non-static nested class Node.\n *  See {@link Bag} for a version that uses a static nested class.\n *  The <em>add</em>, <em>isEmpty</em>, and <em>size</em> operations\n *  take constant time. Iteration takes time proportional to the number of items.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LinkedBag<Item> implements Iterable<Item> {\n    private Node first;    // beginning of bag\n    private int n;         // number of elements in bag\n\n    // helper linked list class\n    private class Node {\n        private Item item;\n        private Node next;\n    }\n\n    /**\n     * Initializes an empty bag.\n     */\n    public LinkedBag() {\n        first = null;\n        n = 0;\n    }\n\n    /**\n     * Is this bag empty?\n     * @return true if this bag is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return first == null;\n    }\n\n    /**\n     * Returns the number of items in this bag.\n     * @return the number of items in this bag\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Adds the item to this bag.\n     * @param item the item to add to this bag\n     */\n    public void add(Item item) {\n        Node oldfirst = first;\n        first = new Node();\n        first.item = item;\n        first.next = oldfirst;\n        n++;\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the items in the bag.\n     */\n    public Iterator<Item> iterator()  {\n        return new LinkedIterator();\n    }\n\n    // an iterator over a linked list\n    private class LinkedIterator implements Iterator<Item> {\n        private Node current;\n\n        // creates a new iterator\n        public LinkedIterator() {\n            current = first;\n        }\n\n        // is there a next item in the iterator?\n        public boolean hasNext() {\n            return current != null;\n        }\n\n        // returns the next item in the iterator (and advances the iterator)\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = current.item;\n            current = current.next;\n            return item;\n        }\n    }\n\n    /**\n     * Unit tests the {@code LinkedBag} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        LinkedBag<String> bag = new LinkedBag<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            bag.add(item);\n        }\n\n        StdOut.println(\"size of bag = \" + bag.size());\n        for (String s : bag) {\n            StdOut.println(s);\n        }\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LinkedQueue.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LinkedQueue.java\n *  Execution:    java LinkedQueue < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/13stacks/tobe.txt\n *\n *  A generic queue, implemented using a singly linked list.\n *\n *  % java Queue < tobe.txt\n *  to be or not to be (2 left on queue)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code LinkedQueue} class represents a first-in-first-out (FIFO)\n *  queue of generic items.\n *  It supports the usual <em>enqueue</em> and <em>dequeue</em>\n *  operations, along with methods for peeking at the first item,\n *  testing if the queue is empty, and iterating through\n *  the items in FIFO order.\n *  <p>\n *  This implementation uses a singly linked list with a non-static nested class\n *  for linked-list nodes.  See {@link Queue} for a version that uses a static nested class.\n *  The <em>enqueue</em>, <em>dequeue</em>, <em>peek</em>, <em>size</em>, and <em>is-empty</em>\n *  operations all take constant time in the worst case.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LinkedQueue<Item> implements Iterable<Item> {\n    private int n;         // number of elements on queue\n    private Node first;    // beginning of queue\n    private Node last;     // end of queue\n\n    // helper linked list class\n    private class Node {\n        private Item item;\n        private Node next;\n    }\n\n    /**\n     * Initializes an empty queue.\n     */\n    public LinkedQueue() {\n        first = null;\n        last  = null;\n        n = 0;\n        assert check();\n    }\n\n    /**\n     * Is this queue empty?\n     * @return true if this queue is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return first == null;\n    }\n\n    /**\n     * Returns the number of items in this queue.\n     * @return the number of items in this queue\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns the item least recently added to this queue.\n     * @return the item least recently added to this queue\n     * @throws java.util.NoSuchElementException if this queue is empty\n     */\n    public Item peek() {\n        if (isEmpty()) throw new NoSuchElementException(\"Queue underflow\");\n        return first.item;\n    }\n\n    /**\n     * Adds the item to this queue.\n     * @param item the item to add\n     */\n    public void enqueue(Item item) {\n        Node oldlast = last;\n        last = new Node();\n        last.item = item;\n        last.next = null;\n        if (isEmpty()) first = last;\n        else           oldlast.next = last;\n        n++;\n        assert check();\n    }\n\n    /**\n     * Removes and returns the item on this queue that was least recently added.\n     * @return the item on this queue that was least recently added\n     * @throws java.util.NoSuchElementException if this queue is empty\n     */\n    public Item dequeue() {\n        if (isEmpty()) throw new NoSuchElementException(\"Queue underflow\");\n        Item item = first.item;\n        first = first.next;\n        n--;\n        if (isEmpty()) last = null;   // to avoid loitering\n        assert check();\n        return item;\n    }\n\n    /**\n     * Returns a string representation of this queue.\n     * @return the sequence of items in FIFO order, separated by spaces\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (Item item : this)\n            s.append(item + \" \");\n        return s.toString();\n    }\n\n    // check internal invariants\n    private boolean check() {\n        if (n < 0) {\n            return false;\n        }\n        else if (n == 0) {\n            if (first != null) return false;\n            if (last  != null) return false;\n        }\n        else if (n == 1) {\n            if (first == null || last == null) return false;\n            if (first != last)                 return false;\n            if (first.next != null)            return false;\n        }\n        else {\n            if (first == null || last == null) return false;\n            if (first == last)      return false;\n            if (first.next == null) return false;\n            if (last.next  != null) return false;\n\n            // check internal consistency of instance variable n\n            int numberOfNodes = 0;\n            for (Node x = first; x != null && numberOfNodes <= n; x = x.next) {\n                numberOfNodes++;\n            }\n            if (numberOfNodes != n) return false;\n\n            // check internal consistency of instance variable last\n            Node lastNode = first;\n            while (lastNode.next != null) {\n                lastNode = lastNode.next;\n            }\n            if (last != lastNode) return false;\n        }\n\n        return true;\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the items in this queue in FIFO order.\n     * @return an iterator that iterates over the items in this queue in FIFO order\n     */\n    public Iterator<Item> iterator()  {\n        return new LinkedIterator();\n    }\n\n    // a linked-list iterator\n    private class LinkedIterator implements Iterator<Item> {\n        private Node current = first;\n\n        public boolean hasNext() {\n            return current != null;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = current.item;\n            current = current.next;\n            return item;\n        }\n    }\n\n\n    /**\n     * Unit tests the {@code LinkedQueue} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        LinkedQueue<String> queue = new LinkedQueue<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\"))\n                queue.enqueue(item);\n            else if (!queue.isEmpty())\n                StdOut.print(queue.dequeue() + \" \");\n        }\n        StdOut.println(\"(\" + queue.size() + \" left on queue)\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LinkedStack.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LinkedStack.java\n *  Execution:    java LinkedStack < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/13stacks/tobe.txt\n *\n *  A generic stack, implemented using a linked list. Each stack\n *  element is of type Item.\n *\n *  % more tobe.txt\n *  to be or not to - be - - that - - - is\n *\n *  % java LinkedStack < tobe.txt\n *  to be not that or be (2 left on stack)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n\n/**\n *  The {@code LinkedStack} class represents a last-in-first-out (LIFO) stack of\n *  generic items.\n *  It supports the usual <em>push</em> and <em>pop</em> operations, along with methods\n *  for peeking at the top item, testing if the stack is empty, and iterating through\n *  the items in LIFO order.\n *  <p>\n *  This implementation uses a singly linked list with a non-static nested class for\n *  linked-list nodes. See {@link Stack} for a version that uses a static nested class.\n *  The <em>push</em>, <em>pop</em>, <em>peek</em>, <em>size</em>, and <em>is-empty</em>\n *  operations all take constant time in the worst case.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LinkedStack<Item> implements Iterable<Item> {\n    private int n;          // size of the stack\n    private Node first;     // top of stack\n\n    // helper linked list class\n    private class Node {\n        private Item item;\n        private Node next;\n    }\n\n    /**\n     * Initializes an empty stack.\n     */\n    public LinkedStack() {\n        first = null;\n        n = 0;\n        assert check();\n    }\n\n    /**\n     * Is this stack empty?\n     * @return true if this stack is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return first == null;\n    }\n\n    /**\n     * Returns the number of items in the stack.\n     * @return the number of items in the stack\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Adds the item to this stack.\n     * @param item the item to add\n     */\n    public void push(Item item) {\n        Node oldfirst = first;\n        first = new Node();\n        first.item = item;\n        first.next = oldfirst;\n        n++;\n        assert check();\n    }\n\n    /**\n     * Removes and returns the item most recently added to this stack.\n     * @return the item most recently added\n     * @throws java.util.NoSuchElementException if this stack is empty\n     */\n    public Item pop() {\n        if (isEmpty()) throw new NoSuchElementException(\"Stack underflow\");\n        Item item = first.item;        // save item to return\n        first = first.next;            // delete first node\n        n--;\n        assert check();\n        return item;                   // return the saved item\n    }\n\n\n    /**\n     * Returns (but does not remove) the item most recently added to this stack.\n     * @return the item most recently added to this stack\n     * @throws java.util.NoSuchElementException if this stack is empty\n     */\n    public Item peek() {\n        if (isEmpty()) throw new NoSuchElementException(\"Stack underflow\");\n        return first.item;\n    }\n\n    /**\n     * Returns a string representation of this stack.\n     * @return the sequence of items in the stack in LIFO order, separated by spaces\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (Item item : this)\n            s.append(item + \" \");\n        return s.toString();\n    }\n\n    /**\n     * Returns an iterator to this stack that iterates through the items in LIFO order.\n     * @return an iterator to this stack that iterates through the items in LIFO order.\n     */\n    public Iterator<Item> iterator() {\n        return new LinkedIterator();\n    }\n\n    // a linked-list iterator\n    private class LinkedIterator implements Iterator<Item> {\n        private Node current = first;\n\n        public boolean hasNext() {\n            return current != null;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = current.item;\n            current = current.next;\n            return item;\n        }\n    }\n\n\n    // check internal invariants\n    private boolean check() {\n\n        // check a few properties of instance variable 'first'\n        if (n < 0) {\n            return false;\n        }\n        if (n == 0) {\n            if (first != null) return false;\n        }\n        else if (n == 1) {\n            if (first == null)      return false;\n            if (first.next != null) return false;\n        }\n        else {\n            if (first == null)      return false;\n            if (first.next == null) return false;\n        }\n\n        // check internal consistency of instance variable n\n        int numberOfNodes = 0;\n        for (Node x = first; x != null && numberOfNodes <= n; x = x.next) {\n            numberOfNodes++;\n        }\n        if (numberOfNodes != n) return false;\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code LinkedStack} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        LinkedStack<String> stack = new LinkedStack<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\"))\n                stack.push(item);\n            else if (!stack.isEmpty())\n                StdOut.print(stack.pop() + \" \");\n        }\n        StdOut.println(\"(\" + stack.size() + \" left on stack)\");\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LongestCommonSubstring.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LongestCommonSubstring.java\n *  Execution:    java  LongestCommonSubstring file1.txt file2.txt\n *  Dependencies: SuffixArray.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/63suffix/tale.txt\n *                https://algs4.cs.princeton.edu/63suffix/mobydick.txt\n *\n *  Read in two text files and find the longest substring that\n *  appears in both texts.\n *\n *  % java LongestCommonSubstring tale.txt mobydick.txt\n *  ' seemed on the point of being '\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LongestCommonSubstring} class provides a {@link SuffixArray}\n *  client for computing the longest common substring that appears in two\n *  given strings.\n *  <p>\n *  This implementation computes the suffix array of each string and applies a\n *  merging operation to determine the longest common substring.\n *  For an alternate implementation, see\n *  <a href = \"https://algs4.cs.princeton.edu/63suffix/LongestCommonSubstringConcatenate.java.html\">LongestCommonSubstringConcatenate.java</a>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/63suffix\">Section 6.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  <p>\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LongestCommonSubstring {\n\n    // Do not instantiate.\n    private LongestCommonSubstring() { }\n\n    // return the longest common prefix of suffix s[p..] and suffix t[q..]\n    private static String lcp(String s, int p, String t, int q) {\n        int n = Math.min(s.length() - p, t.length() - q);\n        for (int i = 0; i < n; i++) {\n            if (s.charAt(p + i) != t.charAt(q + i))\n                return s.substring(p, p + i);\n        }\n        return s.substring(p, p + n);\n    }\n\n    // compare suffix s[p..] and suffix t[q..]\n    private static int compare(String s, int p, String t, int q) {\n        int n = Math.min(s.length() - p, t.length() - q);\n        for (int i = 0; i < n; i++) {\n            if (s.charAt(p + i) != t.charAt(q + i))\n                return s.charAt(p+i) - t.charAt(q+i);\n        }\n        if      (s.length() - p < t.length() - q) return -1;\n        else if (s.length() - p > t.length() - q) return +1;\n        else                                      return  0;\n    }\n\n    /**\n     * Returns the longest common string of the two specified strings.\n     *\n     * @param  s one string\n     * @param  t the other string\n     * @return the longest common string that appears as a substring\n     *         in both {@code s} and {@code t}; the empty string\n     *         if no such string\n     */\n    public static String lcs(String s, String t) {\n        SuffixArray suffix1 = new SuffixArray(s);\n        SuffixArray suffix2 = new SuffixArray(t);\n\n        // find longest common substring by \"merging\" sorted suffixes\n        String lcs = \"\";\n        int i = 0, j = 0;\n        while (i < s.length() && j < t.length()) {\n            int p = suffix1.index(i);\n            int q = suffix2.index(j);\n            String x = lcp(s, p, t, q);\n            if (x.length() > lcs.length()) lcs = x;\n            if (compare(s, p, t, q) < 0) i++;\n            else                         j++;\n        }\n        return lcs;\n    }\n\n    /**\n     * Unit tests the {@code lcs()} method.\n     * Reads in two strings from files specified as command-line arguments;\n     * computes the longest common substring; and prints the results to\n     * standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in1 = new In(args[0]);\n        In in2 = new In(args[1]);\n        String s = in1.readAll().trim().replaceAll(\"\\\\s+\", \" \");\n        String t = in2.readAll().trim().replaceAll(\"\\\\s+\", \" \");\n        StdOut.println(\"'\" + lcs(s, t) + \"'\");\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LongestRepeatedSubstring.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LongestRepeatedSubstring.java\n *  Execution:    java LongestRepeatedSubstring < file.txt\n *  Dependencies: StdIn.java SuffixArray.java\n *  Data files:   https://algs4.cs.princeton.edu/63suffix/tale.txt\n *                https://algs4.cs.princeton.edu/63suffix/tinyTale.txt\n *                https://algs4.cs.princeton.edu/63suffix/mobydick.txt\n *\n *  Reads a text string from standard input, replaces all consecutive blocks\n *  of whitespace with a single space, and then computes the longest\n *  repeated substring in that text using a suffix array.\n *\n *  % java LongestRepeatedSubstring < tinyTale.txt\n *  'st of times it was the '\n *\n *  % java LongestRepeatedSubstring < mobydick.txt\n *  ',- Such a funny, sporty, gamy, jesty, joky, hoky-poky lad, is the Ocean, oh! Th'\n *\n *  % java LongestRepeatedSubstring\n *  aaaaaaaaa\n *  'aaaaaaaa'\n *\n *  % java LongestRepeatedSubstring\n *  abcdefg\n *  ''\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LongestRepeatedSubstring} class provides a {@link SuffixArray}\n *  client for computing the longest repeated substring of a string that\n *  appears at least twice. The repeated substrings may overlap (but must\n *  be distinct).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/63suffix\">Section 6.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  <p>\n *  See also {@link LongestCommonSubstring}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LongestRepeatedSubstring {\n\n    // Do not instantiate.\n    private LongestRepeatedSubstring() { }\n\n    /**\n     * Returns the longest common string of the two specified strings.\n     *\n     * @param  s one string\n     * @param  t the other string\n     * @return the longest common string that appears as a substring\n     */\n\n    /**\n     * Returns the longest repeated substring of the specified string.\n     *\n     * @param  text the string\n     * @return the longest repeated substring that appears in {@code text};\n     *         the empty string if no such string\n     */\n    public static String lrs(String text) {\n        int n = text.length();\n        SuffixArray sa = new SuffixArray(text);\n        String lrs = \"\";\n        for (int i = 1; i < n; i++) {\n            int length = sa.lcp(i);\n            if (length > lrs.length()) {\n                // lrs = sa.select(i).substring(0, length);\n                lrs = text.substring(sa.index(i), sa.index(i) + length);\n            }\n        }\n        return lrs;\n    }\n\n    /**\n     * Unit tests the {@code lrs()} method.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String text = StdIn.readAll().replaceAll(\"\\\\s+\", \" \");\n        StdOut.println(\"'\" + lrs(text) + \"'\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LookupCSV.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LookupCSV.java\n *  Execution:    java LookupCSV file.csv keyField valField\n *  Dependencies: ST.java In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/DJIA.csv\n *                https://algs4.cs.princeton.edu/35applications/UPC.csv\n *                https://algs4.cs.princeton.edu/35applications/amino.csv\n *                https://algs4.cs.princeton.edu/35applications/elements.csv\n *                https://algs4.cs.princeton.edu/35applications/ip.csv\n *                https://algs4.cs.princeton.edu/35applications/morse.csv\n *\n *  Reads in a set of key-value pairs from a two-column CSV file\n *  specified on the command line; then, reads in keys from standard\n *  input and prints out corresponding values.\n *\n *  % java LookupCSV amino.csv 0 3     % java LookupCSV ip.csv 0 1\n *  TTA                                www.google.com\n *  Leucine                            216.239.41.99\n *  ABC\n *  Not found                          % java LookupCSV ip.csv 1 0\n *  TCT                                216.239.41.99\n *  Serine                             www.google.com\n *\n *  % java LookupCSV amino.csv 3 0     % java LookupCSV DJIA.csv 0 1\n *  Glycine                            29-Oct-29\n *  GGG                                252.38\n *                                     20-Oct-87\n *                                     1738.74\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LookupCSV} class provides a data-driven client for reading in a\n *  key-value pairs from a file; then, printing the values corresponding to the\n *  keys found on standard input. Both keys and values are strings.\n *  The fields to serve as the key and value are taken as command-line arguments.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LookupCSV {\n\n    // Do not instantiate.\n    private LookupCSV() { }\n\n    public static void main(String[] args) {\n        int keyField = Integer.parseInt(args[1]);\n        int valField = Integer.parseInt(args[2]);\n\n        // symbol table\n        ST<String, String> st = new ST<String, String>();\n\n        // read in the data from csv file\n        In in = new In(args[0]);\n        while (in.hasNextLine()) {\n            String line = in.readLine();\n            String[] tokens = line.split(\",\");\n            String key = tokens[keyField];\n            String val = tokens[valField];\n            st.put(key, val);\n        }\n\n        while (!StdIn.isEmpty()) {\n            String s = StdIn.readString();\n            if (st.contains(s)) StdOut.println(st.get(s));\n            else                StdOut.println(\"Not found\");\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/LookupIndex.java",
    "content": "/******************************************************************************\n *  Compilation:  javac LookupIndex.java\n *  Execution:    java LookupIndex movies.txt \"/\"\n *  Dependencies: ST.java Queue.java In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/aminoI.csv\n *                https://algs4.cs.princeton.edu/35applications/movies.txt\n *\n *  % java LookupIndex aminoI.csv \",\"\n *  Serine\n *    TCT\n *    TCA\n *    TCG\n *    AGT\n *    AGC\n *  TCG\n *    Serine\n *\n *  % java LookupIndex movies.txt \"/\"\n *  Bacon, Kevin\n *    Animal House (1978)\n *    Apollo 13 (1995)\n *    Beauty Shop (2005)\n *    Diner (1982)\n *    Few Good Men, A (1992)\n *    Flatliners (1990)\n *    Footloose (1984)\n *    Friday the 13th (1980)\n *    ...\n *  Tin Men (1987)\n *    DeBoy, David\n *    Blumenfeld, Alan\n *    ...\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code LookupIndex} class provides a data-driven client for reading in a\n *  key-value pairs from a file; then, printing the values corresponding to the\n *  keys found on standard input. Keys are strings; values are lists of strings.\n *  The separating delimiter is taken as a command-line argument. This client\n *  is sometimes known as an <em>inverted index</em>.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class LookupIndex {\n\n    // Do not instantiate.\n    private LookupIndex() { }\n\n    public static void main(String[] args) {\n        String filename  = args[0];\n        String separator = args[1];\n        In in = new In(filename);\n\n        ST<String, Queue<String>> st = new ST<String, Queue<String>>();\n        ST<String, Queue<String>> ts = new ST<String, Queue<String>>();\n\n        while (in.hasNextLine()) {\n            String line = in.readLine();\n            String[] fields = line.split(separator);\n            String key = fields[0];\n            for (int i = 1; i < fields.length; i++) {\n                String val = fields[i];\n                if (!st.contains(key)) st.put(key, new Queue<String>());\n                if (!ts.contains(val)) ts.put(val, new Queue<String>());\n                st.get(key).enqueue(val);\n                ts.get(val).enqueue(key);\n            }\n        }\n\n        StdOut.println(\"Done indexing\");\n\n        // read queries from standard input, one per line\n        while (!StdIn.isEmpty()) {\n            String query = StdIn.readLine();\n            if (st.contains(query))\n                for (String vals : st.get(query))\n                    StdOut.println(\"  \" + vals);\n            if (ts.contains(query))\n                for (String keys : ts.get(query))\n                    StdOut.println(\"  \" + keys);\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/MSD.java",
    "content": "/******************************************************************************\n *  Compilation: javac MSD.java\n *  Execution:   java MSD < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/51radix/words3.txt\n *                https://algs4.cs.princeton.edu/51radix/shells.txt\n *\n *  Sort an array of strings or integers using MSD radix sort.\n *\n *  % java MSD < shells.txt\n *  are\n *  by\n *  sea\n *  seashells\n *  seashells\n *  sells\n *  sells\n *  she\n *  she\n *  shells\n *  shore\n *  surely\n *  the\n *  the\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code MSD} class provides static methods for sorting an\n *  array of extended ASCII strings or integers using MSD radix sort.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/51radix\">Section 5.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class MSD {\n    private static final int BITS_PER_BYTE =   8;\n    private static final int BITS_PER_INT  =  32;   // each Java int is 32 bits\n    private static final int R             = 256;   // extended ASCII alphabet size\n    private static final int CUTOFF        =  15;   // cutoff to insertion sort\n\n    // do not instantiate\n    private MSD() { }\n\n   /**\n     * Rearranges the array of extended ASCII strings in ascending order.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(String[] a) {\n        int n = a.length;\n        String[] aux = new String[n];\n        sort(a, 0, n-1, 0, aux);\n    }\n\n    // return dth character of s, -1 if d = length of string\n    private static int charAt(String s, int d) {\n        assert d >= 0 && d <= s.length();\n        if (d == s.length()) return -1;\n        return s.charAt(d);\n    }\n\n    // sort from a[lo] to a[hi], starting at the dth character\n    private static void sort(String[] a, int lo, int hi, int d, String[] aux) {\n\n        // cutoff to insertion sort for small subarrays\n        if (hi <= lo + CUTOFF) {\n            insertion(a, lo, hi, d);\n            return;\n        }\n\n        // compute frequency counts\n        int[] count = new int[R+2];\n        for (int i = lo; i <= hi; i++) {\n            int c = charAt(a[i], d);\n            count[c+2]++;\n        }\n\n        // transform counts to indices\n        for (int r = 0; r < R+1; r++)\n            count[r+1] += count[r];\n\n        // distribute\n        for (int i = lo; i <= hi; i++) {\n            int c = charAt(a[i], d);\n            aux[count[c+1]++] = a[i];\n        }\n\n        // copy back\n        for (int i = lo; i <= hi; i++)\n            a[i] = aux[i - lo];\n\n\n        // recursively sort for each character (excludes sentinel -1)\n        for (int r = 0; r < R; r++)\n            sort(a, lo + count[r], lo + count[r+1] - 1, d+1, aux);\n    }\n\n\n    // insertion sort a[lo..hi], starting at dth character\n    private static void insertion(String[] a, int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], d); j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(String[] a, int i, int j) {\n        String temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n    // is v less than w, starting at character d\n    private static boolean less(String v, String w, int d) {\n        // assert v.substring(0, d).equals(w.substring(0, d));\n        for (int i = d; i < Math.min(v.length(), w.length()); i++) {\n            if (v.charAt(i) < w.charAt(i)) return true;\n            if (v.charAt(i) > w.charAt(i)) return false;\n        }\n        return v.length() < w.length();\n    }\n\n\n   /**\n     * Rearranges the array of 32-bit integers in ascending order.\n     * Currently assumes that the integers are nonnegative.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(int[] a) {\n        int n = a.length;\n        int[] aux = new int[n];\n        sort(a, 0, n-1, 0, aux);\n    }\n\n    // MSD sort from a[lo] to a[hi], starting at the dth byte\n    private static void sort(int[] a, int lo, int hi, int d, int[] aux) {\n\n        // cutoff to insertion sort for small subarrays\n        if (hi <= lo + CUTOFF) {\n            insertion(a, lo, hi);\n            return;\n        }\n\n        // compute frequency counts (need R = 256)\n        int[] count = new int[R+1];\n        int mask = R - 1;   // 0xFF;\n        int shift = BITS_PER_INT - BITS_PER_BYTE*d - BITS_PER_BYTE;\n        for (int i = lo; i <= hi; i++) {\n            int c = (a[i] >> shift) & mask;\n            count[c + 1]++;\n        }\n\n        // transform counts to indices\n        for (int r = 0; r < R; r++)\n            count[r+1] += count[r];\n\n        // for most significant byte, 0x80-0xFF comes before 0x00-0x7F\n        if (d == 0) {\n            int shift1 = count[R] - count[R/2];\n            int shift2 = count[R/2];\n            count[R] = shift1 + count[1];   // to simplify recursive calls later\n            for (int r = 0; r < R/2; r++)\n                count[r] += shift1;\n            for (int r = R/2; r < R; r++)\n                count[r] -= shift2;\n        }\n\n        // distribute\n        for (int i = lo; i <= hi; i++) {\n            int c = (a[i] >> shift) & mask;\n            aux[count[c]++] = a[i];\n        }\n\n        // copy back\n        for (int i = lo; i <= hi; i++)\n            a[i] = aux[i - lo];\n\n        // no more bits\n        if (d == 3) return;\n\n        // special case for most significant byte\n        if (d == 0 && count[R/2] > 0)\n            sort(a, lo, lo + count[R/2] - 1, d+1, aux);\n\n        // special case for other bytes\n        if (d != 0 && count[0] > 0)\n            sort(a, lo, lo + count[0] - 1, d+1, aux);\n\n        // recursively sort for each character\n        // (could skip r = R/2 for d = 0 and skip r = R for d > 0)\n        for (int r = 0; r < R; r++)\n            if (count[r+1] > count[r])\n                sort(a, lo + count[r], lo + count[r+1] - 1, d+1, aux);\n    }\n\n    // insertion sort a[lo..hi]\n    private static void insertion(int[] a, int lo, int hi) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && a[j] < a[j-1]; j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(int[] a, int i, int j) {\n        int temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n\n    /**\n     * Reads in a sequence of extended ASCII strings from standard input;\n     * MSD radix sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        int n = a.length;\n        sort(a);\n        for (int i = 0; i < n; i++)\n            StdOut.println(a[i]);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/MaxPQ.java",
    "content": "/******************************************************************************\n *  Compilation:  javac MaxPQ.java\n *  Execution:    java MaxPQ < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/24pq/tinyPQ.txt\n *\n *  Generic max priority queue implementation with a binary heap.\n *  Can be used with a comparator instead of the natural order,\n *  but the generic Key type must still be Comparable.\n *\n *  % java MaxPQ < tinyPQ.txt\n *  Q X P (6 left on pq)\n *\n *  We use a one-based array to simplify parent and child calculations.\n *\n *  Can be optimized by replacing full exchanges with half exchanges\n *  (ala insertion sort).\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code MaxPQ} class represents a priority queue of generic keys.\n *  It supports the usual <em>insert</em> and <em>delete-the-maximum</em>\n *  operations, along with methods for peeking at the maximum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  <p>\n *  This implementation uses a <em>binary heap</em>.\n *  The <em>insert</em> and <em>delete-the-maximum</em> operations take\n *  &Theta;(log <em>n</em>) amortized time, where <em>n</em> is the number\n *  of elements in the priority queue. This is an amortized bound\n *  (and not a worst-case bound) because of array resizing operations.\n *  The <em>min</em>, <em>size</em>, and <em>is-empty</em> operations take\n *  &Theta;(1) time in the worst case.\n *  Construction takes time proportional to the specified capacity or the\n *  number of items used to initialize the data structure.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Key> the generic type of key on this priority queue\n */\n\npublic class MaxPQ<Key> implements Iterable<Key> {\n    private Key[] pq;                    // store items at indices 1 to n\n    private int n;                       // number of items on priority queue\n    private Comparator<Key> comparator;  // optional comparator\n\n    /**\n     * Initializes an empty priority queue with the given initial capacity.\n     *\n     * @param  initCapacity the initial capacity of this priority queue\n     */\n    public MaxPQ(int initCapacity) {\n        pq = (Key[]) new Object[initCapacity + 1];\n        n = 0;\n    }\n\n    /**\n     * Initializes an empty priority queue.\n     */\n    public MaxPQ() {\n        this(1);\n    }\n\n    /**\n     * Initializes an empty priority queue with the given initial capacity,\n     * using the given comparator.\n     *\n     * @param  initCapacity the initial capacity of this priority queue\n     * @param  comparator the order in which to compare the keys\n     */\n    public MaxPQ(int initCapacity, Comparator<Key> comparator) {\n        this.comparator = comparator;\n        pq = (Key[]) new Object[initCapacity + 1];\n        n = 0;\n    }\n\n    /**\n     * Initializes an empty priority queue using the given comparator.\n     *\n     * @param  comparator the order in which to compare the keys\n     */\n    public MaxPQ(Comparator<Key> comparator) {\n        this(1, comparator);\n    }\n\n    /**\n     * Initializes a priority queue from the array of keys.\n     * Takes time proportional to the number of keys, using sink-based heap construction.\n     *\n     * @param  keys the array of keys\n     */\n    public MaxPQ(Key[] keys) {\n        n = keys.length;\n        pq = (Key[]) new Object[keys.length + 1];\n        for (int i = 0; i < n; i++)\n            pq[i+1] = keys[i];\n        for (int k = n/2; k >= 1; k--)\n            sink(k);\n        assert isMaxHeap();\n    }\n\n\n\n    /**\n     * Returns true if this priority queue is empty.\n     *\n     * @return {@code true} if this priority queue is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Returns the number of keys on this priority queue.\n     *\n     * @return the number of keys on this priority queue\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns a largest key on this priority queue.\n     *\n     * @return a largest key on this priority queue\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"Priority queue underflow\");\n        return pq[1];\n    }\n\n    // resize the underlying array to have the given capacity\n    private void resize(int capacity) {\n        assert capacity > n;\n        Key[] temp = (Key[]) new Object[capacity];\n        for (int i = 1; i <= n; i++) {\n            temp[i] = pq[i];\n        }\n        pq = temp;\n    }\n\n\n    /**\n     * Adds a new key to this priority queue.\n     *\n     * @param  x the new key to add to this priority queue\n     */\n    public void insert(Key x) {\n\n        // double size of array if necessary\n        if (n == pq.length - 1) resize(2 * pq.length);\n\n        // add x, and percolate it up to maintain heap invariant\n        pq[++n] = x;\n        swim(n);\n        assert isMaxHeap();\n    }\n\n    /**\n     * Removes and returns a largest key on this priority queue.\n     *\n     * @return a largest key on this priority queue\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public Key delMax() {\n        if (isEmpty()) throw new NoSuchElementException(\"Priority queue underflow\");\n        Key max = pq[1];\n        exch(1, n--);\n        sink(1);\n        pq[n+1] = null;     // to avoid loitering and help with garbage collection\n        if ((n > 0) && (n == (pq.length - 1) / 4)) resize(pq.length / 2);\n        assert isMaxHeap();\n        return max;\n    }\n\n\n   /***************************************************************************\n    * Helper functions to restore the heap invariant.\n    ***************************************************************************/\n\n    private void swim(int k) {\n        while (k > 1 && less(k/2, k)) {\n            exch(k/2, k);\n            k = k/2;\n        }\n    }\n\n    private void sink(int k) {\n        while (2*k <= n) {\n            int j = 2*k;\n            if (j < n && less(j, j+1)) j++;\n            if (!less(k, j)) break;\n            exch(k, j);\n            k = j;\n        }\n    }\n\n   /***************************************************************************\n    * Helper functions for compares and swaps.\n    ***************************************************************************/\n    private boolean less(int i, int j) {\n        if (comparator == null) {\n            return ((Comparable<Key>) pq[i]).compareTo(pq[j]) < 0;\n        }\n        else {\n            return comparator.compare(pq[i], pq[j]) < 0;\n        }\n    }\n\n    private void exch(int i, int j) {\n        Key swap = pq[i];\n        pq[i] = pq[j];\n        pq[j] = swap;\n    }\n\n    // is pq[1..n] a max heap?\n    private boolean isMaxHeap() {\n        for (int i = 1; i <= n; i++) {\n            if (pq[i] == null) return false;\n        }\n        for (int i = n+1; i < pq.length; i++) {\n            if (pq[i] != null) return false;\n        }\n        if (pq[0] != null) return false;\n        return isMaxHeapOrdered(1);\n    }\n\n    // is subtree of pq[1..n] rooted at k a max heap?\n    private boolean isMaxHeapOrdered(int k) {\n        if (k > n) return true;\n        int left = 2*k;\n        int right = 2*k + 1;\n        if (left  <= n && less(k, left))  return false;\n        if (right <= n && less(k, right)) return false;\n        return isMaxHeapOrdered(left) && isMaxHeapOrdered(right);\n    }\n\n\n   /***************************************************************************\n    * Iterator.\n    ***************************************************************************/\n\n    /**\n     * Returns an iterator that iterates over the keys on this priority queue\n     * in descending order.\n     * The iterator doesn't implement {@code remove()} since it's optional.\n     *\n     * @return an iterator that iterates over the keys in descending order\n     */\n    public Iterator<Key> iterator() {\n        return new HeapIterator();\n    }\n\n    private class HeapIterator implements Iterator<Key> {\n\n        // create a new pq\n        private MaxPQ<Key> copy;\n\n        // add all items to copy of heap\n        // takes linear time since already in heap order so no keys move\n        public HeapIterator() {\n            if (comparator == null) copy = new MaxPQ<Key>(size());\n            else                    copy = new MaxPQ<Key>(size(), comparator);\n            for (int i = 1; i <= n; i++)\n                copy.insert(pq[i]);\n        }\n\n        public boolean hasNext()  { return !copy.isEmpty();                     }\n        public void remove()      { throw new UnsupportedOperationException();  }\n\n        public Key next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            return copy.delMax();\n        }\n    }\n\n    /**\n     * Unit tests the {@code MaxPQ} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        MaxPQ<String> pq = new MaxPQ<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\")) pq.insert(item);\n            else if (!pq.isEmpty()) StdOut.print(pq.delMax() + \" \");\n        }\n        StdOut.println(\"(\" + pq.size() + \" left on pq)\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Merge.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Merge.java\n *  Execution:    java Merge < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/22mergesort/tiny.txt\n *                https://algs4.cs.princeton.edu/22mergesort/words3.txt\n *\n *  Sorts a sequence of strings from standard input using mergesort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Merge < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Merge < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Merge} class provides static methods for sorting an\n *  array using a top-down, recursive version of <em>mergesort</em>.\n *  <p>\n *  This implementation takes &Theta;(<em>n</em> log <em>n</em>) time\n *  to sort any array of length <em>n</em> (assuming comparisons\n *  take constant time). It makes between\n *  ~ &frac12; <em>n</em> log<sub>2</sub> <em>n</em> and\n *  ~ 1 <em>n</em> log<sub>2</sub> <em>n</em> compares.\n *  <p>\n *  This sorting algorithm is stable.\n *  It uses &Theta;(<em>n</em>) extra memory (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/22mergesort\">Section 2.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For an optimized version, see {@link MergeX}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Merge {\n\n    // This class should not be instantiated.\n    private Merge() { }\n\n    // stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]\n    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {\n        // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays\n        assert isSorted(a, lo, mid);\n        assert isSorted(a, mid+1, hi);\n\n        // copy to aux[]\n        for (int k = lo; k <= hi; k++) {\n            aux[k] = a[k];\n        }\n\n        // merge back to a[]\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)              a[k] = aux[j++];\n            else if (j > hi)               a[k] = aux[i++];\n            else if (less(aux[j], aux[i])) a[k] = aux[j++];\n            else                           a[k] = aux[i++];\n        }\n\n        // postcondition: a[lo .. hi] is sorted\n        assert isSorted(a, lo, hi);\n    }\n\n    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]\n    private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {\n        if (hi <= lo) return;\n        int mid = lo + (hi - lo) / 2;\n        sort(a, aux, lo, mid);\n        sort(a, aux, mid + 1, hi);\n        merge(a, aux, lo, mid, hi);\n    }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        Comparable[] aux = new Comparable[a.length];\n        sort(a, aux, 0, a.length-1);\n        assert isSorted(a);\n    }\n\n\n   /***************************************************************************\n    *  Helper sorting function.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length - 1);\n    }\n\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n\n   /***************************************************************************\n    *  Index mergesort.\n    ***************************************************************************/\n    // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]\n    private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) {\n\n        // copy to aux[]\n        for (int k = lo; k <= hi; k++) {\n            aux[k] = index[k];\n        }\n\n        // merge back to a[]\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)                    index[k] = aux[j++];\n            else if (j > hi)                     index[k] = aux[i++];\n            else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++];\n            else                                 index[k] = aux[i++];\n        }\n    }\n\n    /**\n     * Returns a permutation that gives the elements in the array in ascending order.\n     * @param a the array\n     * @return a permutation {@code p[]} such that {@code a[p[0]]}, {@code a[p[1]]},\n     *    ..., {@code a[p[n-1]]} are in ascending order\n     */\n    public static int[] indexSort(Comparable[] a) {\n        int n = a.length;\n        int[] index = new int[n];\n        for (int i = 0; i < n; i++)\n            index[i] = i;\n\n        int[] aux = new int[n];\n        sort(a, index, aux, 0, n-1);\n        return index;\n    }\n\n    // mergesort a[lo..hi] using auxiliary array aux[lo..hi]\n    private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) {\n        if (hi <= lo) return;\n        int mid = lo + (hi - lo) / 2;\n        sort(a, index, aux, lo, mid);\n        sort(a, index, aux, mid + 1, hi);\n        merge(a, index, aux, lo, mid, hi);\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; mergesorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Merge.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/MergeBU.java",
    "content": "/******************************************************************************\n *  Compilation:  javac MergeBU.java\n *  Execution:    java MergeBU < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/22mergesort/tiny.txt\n *                https://algs4.cs.princeton.edu/22mergesort/words3.txt\n *\n *  Sorts a sequence of strings from standard input using\n *  bottom-up mergesort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java MergeBU < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java MergeBU < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code MergeBU} class provides static methods for sorting an\n *  array using <em>bottom-up mergesort</em>. It is non-recursive.\n *  <p>\n *  This implementation takes &Theta;(<em>n</em> log <em>n</em>) time\n *  to sort any array of length <em>n</em> (assuming comparisons\n *  take constant time). It makes between\n *  ~ &frac12; <em>n</em> log<sub>2</sub> <em>n</em> and\n *  ~ 1 <em>n</em> log<sub>2</sub> <em>n</em> compares.\n *  <p>\n *  This sorting algorithm is stable.\n *  It uses &Theta;(<em>n</em>) extra memory (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/21elementary\">Section 2.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class MergeBU {\n\n    // This class should not be instantiated.\n    private MergeBU() { }\n\n    // stably merge a[lo..mid] with a[mid+1..hi] using aux[lo..hi]\n    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {\n\n        // copy to aux[]\n        for (int k = lo; k <= hi; k++) {\n            aux[k] = a[k];\n        }\n\n        // merge back to a[]\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)              a[k] = aux[j++];  // this copying is unnecessary\n            else if (j > hi)               a[k] = aux[i++];\n            else if (less(aux[j], aux[i])) a[k] = aux[j++];\n            else                           a[k] = aux[i++];\n        }\n\n    }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        int n = a.length;\n        Comparable[] aux = new Comparable[n];\n        for (int len = 1; len < n; len *= 2) {\n            for (int lo = 0; lo < n-len; lo += len+len) {\n                int mid  = lo+len-1;\n                int hi = Math.min(lo+len+len-1, n-1);\n                merge(a, aux, lo, mid, hi);\n            }\n        }\n        assert isSorted(a);\n    }\n\n  /***********************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; bottom-up\n     * mergesorts them; and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        MergeBU.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/MergeX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac MergeX.java\n *  Execution:    java MergeX < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/22mergesort/tiny.txt\n *                https://algs4.cs.princeton.edu/22mergesort/words3.txt\n *\n *  Sorts a sequence of strings from standard input using an\n *  optimized version of mergesort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java MergeX < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java MergeX < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\n\n/**\n *  The {@code MergeX} class provides static methods for sorting an\n *  array using an optimized version of mergesort.\n *  <p>\n *  In the worst case, this implementation takes\n *  &Theta;(<em>n</em> log <em>n</em>) time to sort an array of\n *  length <em>n</em> (assuming comparisons take constant time).\n *  <p>\n *  This sorting algorithm is stable.\n *  It uses &Theta;(<em>n</em>) extra memory (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/22mergesort\">Section 2.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class MergeX {\n    private static final int CUTOFF = 7;  // cutoff to insertion sort\n\n    // This class should not be instantiated.\n    private MergeX() { }\n\n    private static void merge(Comparable[] src, Comparable[] dst, int lo, int mid, int hi) {\n\n        // precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays\n        assert isSorted(src, lo, mid);\n        assert isSorted(src, mid+1, hi);\n\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)              dst[k] = src[j++];\n            else if (j > hi)               dst[k] = src[i++];\n            else if (less(src[j], src[i])) dst[k] = src[j++];   // to ensure stability\n            else                           dst[k] = src[i++];\n        }\n\n        // postcondition: dst[lo .. hi] is sorted subarray\n        assert isSorted(dst, lo, hi);\n    }\n\n    private static void sort(Comparable[] src, Comparable[] dst, int lo, int hi) {\n        // if (hi <= lo) return;\n        if (hi <= lo + CUTOFF) {\n            insertionSort(dst, lo, hi);\n            return;\n        }\n        int mid = lo + (hi - lo) / 2;\n        sort(dst, src, lo, mid);\n        sort(dst, src, mid+1, hi);\n\n        // if (!less(src[mid+1], src[mid])) {\n        //    for (int i = lo; i <= hi; i++) dst[i] = src[i];\n        //    return;\n        // }\n\n        // using System.arraycopy() is a bit faster than the above loop\n        if (!less(src[mid+1], src[mid])) {\n            System.arraycopy(src, lo, dst, lo, hi - lo + 1);\n            return;\n        }\n\n        merge(src, dst, lo, mid, hi);\n    }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        Comparable[] aux = a.clone();\n        sort(aux, a, 0, a.length-1);\n        assert isSorted(a);\n    }\n\n    // sort from a[lo] to a[hi] using insertion sort\n    private static void insertionSort(Comparable[] a, int lo, int hi) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1]); j--)\n                exch(a, j, j-1);\n    }\n\n\n    /*******************************************************************\n     *  Utility methods.\n     *******************************************************************/\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n    // is a[i] < a[j]?\n    private static boolean less(Comparable a, Comparable b) {\n        return a.compareTo(b) < 0;\n    }\n\n    // is a[i] < a[j]?\n    private static boolean less(Object a, Object b, Comparator comparator) {\n        return comparator.compare(a, b) < 0;\n    }\n\n\n    /*******************************************************************\n     *  Version that takes Comparator as argument.\n     *******************************************************************/\n\n    /**\n     * Rearranges the array in ascending order, using the provided order.\n     *\n     * @param a the array to be sorted\n     * @param comparator the comparator that defines the total order\n     */\n    public static void sort(Object[] a, Comparator comparator) {\n        Object[] aux = a.clone();\n        sort(aux, a, 0, a.length-1, comparator);\n        assert isSorted(a, comparator);\n    }\n\n    private static void merge(Object[] src, Object[] dst, int lo, int mid, int hi, Comparator comparator) {\n\n        // precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays\n        assert isSorted(src, lo, mid, comparator);\n        assert isSorted(src, mid+1, hi, comparator);\n\n        int i = lo, j = mid+1;\n        for (int k = lo; k <= hi; k++) {\n            if      (i > mid)                          dst[k] = src[j++];\n            else if (j > hi)                           dst[k] = src[i++];\n            else if (less(src[j], src[i], comparator)) dst[k] = src[j++];\n            else                                       dst[k] = src[i++];\n        }\n\n        // postcondition: dst[lo .. hi] is sorted subarray\n        assert isSorted(dst, lo, hi, comparator);\n    }\n\n\n    private static void sort(Object[] src, Object[] dst, int lo, int hi, Comparator comparator) {\n        // if (hi <= lo) return;\n        if (hi <= lo + CUTOFF) {\n            insertionSort(dst, lo, hi, comparator);\n            return;\n        }\n        int mid = lo + (hi - lo) / 2;\n        sort(dst, src, lo, mid, comparator);\n        sort(dst, src, mid+1, hi, comparator);\n\n        // using System.arraycopy() is a bit faster than the above loop\n        if (!less(src[mid+1], src[mid], comparator)) {\n            System.arraycopy(src, lo, dst, lo, hi - lo + 1);\n            return;\n        }\n\n        merge(src, dst, lo, mid, hi, comparator);\n    }\n\n    // sort from a[lo] to a[hi] using insertion sort\n    private static void insertionSort(Object[] a, int lo, int hi, Comparator comparator) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], comparator); j--)\n                exch(a, j, j-1);\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length - 1);\n    }\n\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    private static boolean isSorted(Object[] a, Comparator comparator) {\n        return isSorted(a, 0, a.length - 1, comparator);\n    }\n\n    private static boolean isSorted(Object[] a, int lo, int hi, Comparator comparator) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(a[i], a[i-1], comparator)) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Object[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; mergesorts them\n     * (using an optimized version of mergesort);\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        MergeX.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/MinPQ.java",
    "content": "/******************************************************************************\n *  Compilation:  javac MinPQ.java\n *  Execution:    java MinPQ < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/24pq/tinyPQ.txt\n *\n *  Generic min priority queue implementation with a binary heap.\n *  Can be used with a comparator instead of the natural order.\n *\n *  % java MinPQ < tinyPQ.txt\n *  E A E (6 left on pq)\n *\n *  We use a one-based array to simplify parent and child calculations.\n *\n *  Can be optimized by replacing full exchanges with half exchanges\n *  (ala insertion sort).\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code MinPQ} class represents a priority queue of generic keys.\n *  It supports the usual <em>insert</em> and <em>delete-the-minimum</em>\n *  operations, along with methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  <p>\n *  This implementation uses a <em>binary heap</em>.\n *  The <em>insert</em> and <em>delete-the-minimum</em> operations take\n *  &Theta;(log <em>n</em>) amortized time, where <em>n</em> is the number\n *  of elements in the priority queue. This is an amortized bound\n *  (and not a worst-case bound) because of array resizing operations.\n *  The <em>min</em>, <em>size</em>, and <em>is-empty</em> operations take\n *  &Theta;(1) time in the worst case.\n *  Construction takes time proportional to the specified capacity or the\n *  number of items used to initialize the data structure.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Key> the generic type of key on this priority queue\n */\npublic class MinPQ<Key> implements Iterable<Key> {\n    private Key[] pq;                    // store items at indices 1 to n\n    private int n;                       // number of items on priority queue\n    private Comparator<Key> comparator;  // optional comparator\n\n    /**\n     * Initializes an empty priority queue with the given initial capacity.\n     *\n     * @param  initCapacity the initial capacity of this priority queue\n     */\n    public MinPQ(int initCapacity) {\n        pq = (Key[]) new Object[initCapacity + 1];\n        n = 0;\n    }\n\n    /**\n     * Initializes an empty priority queue.\n     */\n    public MinPQ() {\n        this(1);\n    }\n\n    /**\n     * Initializes an empty priority queue with the given initial capacity,\n     * using the given comparator.\n     *\n     * @param  initCapacity the initial capacity of this priority queue\n     * @param  comparator the order in which to compare the keys\n     */\n    public MinPQ(int initCapacity, Comparator<Key> comparator) {\n        this.comparator = comparator;\n        pq = (Key[]) new Object[initCapacity + 1];\n        n = 0;\n    }\n\n    /**\n     * Initializes an empty priority queue using the given comparator.\n     *\n     * @param  comparator the order in which to compare the keys\n     */\n    public MinPQ(Comparator<Key> comparator) {\n        this(1, comparator);\n    }\n\n    /**\n     * Initializes a priority queue from the array of keys.\n     * <p>\n     * Takes time proportional to the number of keys, using sink-based heap construction.\n     *\n     * @param  keys the array of keys\n     */\n    public MinPQ(Key[] keys) {\n        n = keys.length;\n        pq = (Key[]) new Object[keys.length + 1];\n        for (int i = 0; i < n; i++)\n            pq[i+1] = keys[i];\n        for (int k = n/2; k >= 1; k--)\n            sink(k);\n        assert isMinHeap();\n    }\n\n    /**\n     * Returns true if this priority queue is empty.\n     *\n     * @return {@code true} if this priority queue is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Returns the number of keys on this priority queue.\n     *\n     * @return the number of keys on this priority queue\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns a smallest key on this priority queue.\n     *\n     * @return a smallest key on this priority queue\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"Priority queue underflow\");\n        return pq[1];\n    }\n\n    // resize the underlying array to have the given capacity\n    private void resize(int capacity) {\n        assert capacity > n;\n        Key[] temp = (Key[]) new Object[capacity];\n        for (int i = 1; i <= n; i++) {\n            temp[i] = pq[i];\n        }\n        pq = temp;\n    }\n\n    /**\n     * Adds a new key to this priority queue.\n     *\n     * @param  x the key to add to this priority queue\n     */\n    public void insert(Key x) {\n        // double size of array if necessary\n        if (n == pq.length - 1) resize(2 * pq.length);\n\n        // add x, and percolate it up to maintain heap invariant\n        pq[++n] = x;\n        swim(n);\n        assert isMinHeap();\n    }\n\n    /**\n     * Removes and returns a smallest key on this priority queue.\n     *\n     * @return a smallest key on this priority queue\n     * @throws NoSuchElementException if this priority queue is empty\n     */\n    public Key delMin() {\n        if (isEmpty()) throw new NoSuchElementException(\"Priority queue underflow\");\n        Key min = pq[1];\n        exch(1, n--);\n        sink(1);\n        pq[n+1] = null;     // to avoid loitering and help with garbage collection\n        if ((n > 0) && (n == (pq.length - 1) / 4)) resize(pq.length / 2);\n        assert isMinHeap();\n        return min;\n    }\n\n\n   /***************************************************************************\n    * Helper functions to restore the heap invariant.\n    ***************************************************************************/\n\n    private void swim(int k) {\n        while (k > 1 && greater(k/2, k)) {\n            exch(k/2, k);\n            k = k/2;\n        }\n    }\n\n    private void sink(int k) {\n        while (2*k <= n) {\n            int j = 2*k;\n            if (j < n && greater(j, j+1)) j++;\n            if (!greater(k, j)) break;\n            exch(k, j);\n            k = j;\n        }\n    }\n\n   /***************************************************************************\n    * Helper functions for compares and swaps.\n    ***************************************************************************/\n    private boolean greater(int i, int j) {\n        if (comparator == null) {\n            return ((Comparable<Key>) pq[i]).compareTo(pq[j]) > 0;\n        }\n        else {\n            return comparator.compare(pq[i], pq[j]) > 0;\n        }\n    }\n\n    private void exch(int i, int j) {\n        Key swap = pq[i];\n        pq[i] = pq[j];\n        pq[j] = swap;\n    }\n\n    // is pq[1..n] a min heap?\n    private boolean isMinHeap() {\n        for (int i = 1; i <= n; i++) {\n            if (pq[i] == null) return false;\n        }\n        for (int i = n+1; i < pq.length; i++) {\n            if (pq[i] != null) return false;\n        }\n        if (pq[0] != null) return false;\n        return isMinHeapOrdered(1);\n    }\n\n    // is subtree of pq[1..n] rooted at k a min heap?\n    private boolean isMinHeapOrdered(int k) {\n        if (k > n) return true;\n        int left = 2*k;\n        int right = 2*k + 1;\n        if (left  <= n && greater(k, left))  return false;\n        if (right <= n && greater(k, right)) return false;\n        return isMinHeapOrdered(left) && isMinHeapOrdered(right);\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the keys on this priority queue\n     * in ascending order.\n     * <p>\n     * The iterator doesn't implement {@code remove()} since it's optional.\n     *\n     * @return an iterator that iterates over the keys in ascending order\n     */\n    public Iterator<Key> iterator() {\n        return new HeapIterator();\n    }\n\n    private class HeapIterator implements Iterator<Key> {\n        // create a new pq\n        private MinPQ<Key> copy;\n\n        // add all items to copy of heap\n        // takes linear time since already in heap order so no keys move\n        public HeapIterator() {\n            if (comparator == null) copy = new MinPQ<Key>(size());\n            else                    copy = new MinPQ<Key>(size(), comparator);\n            for (int i = 1; i <= n; i++)\n                copy.insert(pq[i]);\n        }\n\n        public boolean hasNext()  { return !copy.isEmpty();                     }\n        public void remove()      { throw new UnsupportedOperationException();  }\n\n        public Key next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            return copy.delMin();\n        }\n    }\n\n    /**\n     * Unit tests the {@code MinPQ} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        MinPQ<String> pq = new MinPQ<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\")) pq.insert(item);\n            else if (!pq.isEmpty()) StdOut.print(pq.delMin() + \" \");\n        }\n        StdOut.println(\"(\" + pq.size() + \" left on pq)\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Multiway.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Multiway.java\n *  Execution:    java Multiway input1.txt input2.txt input3.txt ...\n *  Dependencies: IndexMinPQ.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/24pq/m1.txt\n *                https://algs4.cs.princeton.edu/24pq/m2.txt\n *                https://algs4.cs.princeton.edu/24pq/m3.txt\n *\n *  Merges together the sorted input stream given as command-line arguments\n *  into a single sorted output stream on standard output.\n *\n *  % more m1.txt\n *  A B C F G I I Z\n *\n *  % more m2.txt\n *  B D H P Q Q\n *\n *  % more m3.txt\n *  A B E F J N\n *\n *  % java Multiway m1.txt m2.txt m3.txt\n *  A A B B B C D E F F G H I I J N P Q Q Z\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Multiway} class provides a client for reading in several\n *  sorted text files and merging them together into a single sorted\n *  text stream.\n *  This implementation uses a {@link IndexMinPQ} to perform the multiway\n *  merge.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class Multiway {\n\n    // This class should not be instantiated.\n    private Multiway() { }\n\n    // merge together the sorted input streams and write the sorted result to standard output\n    private static void merge(In[] streams) {\n        int n = streams.length;\n        IndexMinPQ<String> pq = new IndexMinPQ<String>(n);\n        for (int i = 0; i < n; i++)\n            if (!streams[i].isEmpty())\n                pq.insert(i, streams[i].readString());\n\n        // Extract and print min and read next from its stream.\n        while (!pq.isEmpty()) {\n            StdOut.print(pq.minKey() + \" \");\n            int i = pq.delMin();\n            if (!streams[i].isEmpty())\n                pq.insert(i, streams[i].readString());\n        }\n        StdOut.println();\n    }\n\n\n    /**\n     *  Reads sorted text files specified as command-line arguments;\n     *  merges them together into a sorted output; and writes\n     *  the results to standard output.\n     *  Note: this client does not check that the input files are sorted.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = args.length;\n        In[] streams = new In[n];\n        for (int i = 0; i < n; i++)\n            streams[i] = new In(args[i]);\n        merge(streams);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/MultiwayMinPQ.java",
    "content": "/******************************************************************************\n *  Compilation: javac MultiwayMinPQ.java   \n *  Execution:\n *  \n *  A multiway heap.\n *  \n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.Comparator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The MultiwayMinPQ class represents a priority queue of generic keys.\n *  It supports the usual insert and delete-the-minimum operations.\n *  It also supports methods for peeking at the minimum key,\n *  testing if the priority queue is empty, and iterating through\n *  the keys.\n *  It is possible to build the priority queue using a Comparator.\n *  If not, the natural order relation between the keys will be used.\n *  \n *  This implementation uses a multiway heap.\n *  For simplified notations, logarithm in base d will be referred as log-d\n *  The delete-the-minimum operation takes time proportional to d*log-d(n)\n *  The insert takes time proportional to log-d(n)\n *  The is-empty, min-key and size operations take constant time.\n *  Constructor takes time proportional to the specified capacity.\n *\n *  @author Tristan Claverie\n */\npublic class MultiwayMinPQ<Key> implements Iterable<Key> {\n\tprivate final int d; \t\t\t\t//Dimension of the heap\n\tprivate int n;\t\t\t\t\t\t//Number of keys currently in the heap\n\tprivate int order;\t\t\t\t\t//Number of levels of the tree\n\tprivate Key[] keys;\t\t\t\t\t//Array of keys\n\tprivate final Comparator<Key> comp;\t//Comparator over the keys\n\t\n\t\n    /**\n     * Initializes an empty priority queue\n     * Worst case is O(d)\n     *\n     * @param  d dimension of the heap\n     * @throws java.lang.IllegalArgumentException if {@code d < 2}\n     */\n\tpublic MultiwayMinPQ(int d) {\n\t\tif (d < 2) throw new IllegalArgumentException(\"Dimension should be 2 or over\");\n\t\tthis.d = d;\n\t\torder = 1;\n\t\tkeys = (Key[]) new Comparable[d << 1];\n\t\tcomp = new MyComparator();\n\t}\n\t\n    /**\n     * Initializes an empty priority queue\n     * Worst case is O(d)\n     *\n     * @param  d dimension of the heap\n     * @param  comparator a Comparator over the keys\n     * @throws java.lang.IllegalArgumentException if {@code d < 2}\n     */\n\tpublic MultiwayMinPQ(Comparator<Key> comparator, int d) {\n\t\tif (d < 2) throw new IllegalArgumentException(\"Dimension should be 2 or over\");\n\t\tthis.d = d;\n\t\torder = 1;\n\t\tkeys = (Key[]) new Comparable[d << 1];\n\t\tcomp = comparator;\n\t}\n\t\n    /**\n     * Initializes a priority queue with given indexes\n     * Worst case is O(n*log-d(n))\n     *\n     * @param  d dimension of the heap\n     * @param  a an array of keys\n     * @throws java.lang.IllegalArgumentException if {@code d < 2}\n     */\n\tpublic MultiwayMinPQ(Key[] a, int d) {\n\t\tif (d < 2) throw new IllegalArgumentException(\"Dimension should be 2 or over\");\n\t\tthis.d = d;\n\t\torder = 1;\n\t\tkeys = (Key[]) new Comparable[d << 1];\n\t\tcomp = new MyComparator();\n\t\tfor (Key key : a) insert(key);\n\t}\n\t\n    /**\n     * Initializes a priority queue with given indexes\n     * Worst case is O(a*log-d(n))\n     *\n     * @param  d dimension of the heap\n     * @param  comparator a Comparator over the keys\n     * @param  a an array of keys\n     * @throws java.lang.IllegalArgumentException if {@code d < 2}\n     */\n\tpublic MultiwayMinPQ(Comparator<Key> comparator, Key[] a, int d) {\n\t\tif (d < 2) throw new IllegalArgumentException(\"Dimension should be 2 or over\");\n\t\tthis.d = d;\n\t\torder = 1;\n\t\tkeys = (Key[]) new Comparable[d << 1];\n\t\tcomp = comparator;\n\t\tfor (Key key : a) insert(key);\n\t}\n\n        /**\n\t * Whether the priority queue is empty\n\t * Worst case is O(1)\n\t * @return true if the priority queue is empty, false if not\n\t */\n\tpublic boolean isEmpty() {\n\t\treturn n == 0;\n\t}\n\n\t/**\n\t * Number of elements currently on the priority queue\n\t * Worst case is O(1)\n\t * @return the number of elements on the priority queue\n\t */\n\tpublic int size() {\n\t\treturn n;\n\t}\n\n\t/**\n\t * Puts a Key on the priority queue\n\t * Worst case is O(log-d(n))\n\t * @param key a Key\n\t */\n\tpublic void insert(Key key) {\n\t\tkeys[n+d] = key;\n\t\tswim(n++);\n\t\tif (n == keys.length-d) {\n\t\t\tresize(getN(order+1)+d);\n\t\t\torder++;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the minimum key currently in the queue\n\t * Worst case is O(1)\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key currently in the priority queue\n\t */\n\tpublic Key minKey() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\treturn keys[d];\n\t}\n\n\t/**\n\t * Deletes the minimum key\n\t * Worst case is O(d*log-d(n))\n\t * @throws java.util.NoSuchElementException if the priority queue is empty\n\t * @return the minimum key\n\t */\n\tpublic Key delMin() {\n\t\tif (isEmpty()) throw new NoSuchElementException(\"Priority queue is empty\");\n\t\texch(0, --n);\n\t\tsink(0);\n\t\tKey min = keys[n+d];\n\t\tkeys[n+d] = null;\n\t\tint number = getN(order-2);\n\t\tif(order > 1 && n == number)  {\n\t\t\tresize(number+(int)Math.pow(d, order-1)+d);\n\t\t\torder--;\n\t\t}\n\t\treturn min;\n\t}\n\t\n\t/***************************\n\t * General helper functions\n\t **************************/\n\t\n\t//Compares two keys\n\tprivate boolean greater(int x, int y) {\n\t\tint i = x+d, j = y+d;\n\t\tif (keys[i] == null) return false;\n\t\tif (keys[j] == null) return true;\n\t\treturn comp.compare(keys[i], keys[j]) > 0;\n\t}\n\t\n\t//Exchanges the position of two keys\n\tprivate void exch(int x, int y) {\n\t\tint i = x+d, j = y+d;\n\t\tKey swap = keys[i];\n\t\tkeys[i] = keys[j];\n\t\tkeys[j] = swap;\n\t}\n\t\n\t//Gets the maximum number of keys in the heap, given the number of levels of the tree\n\tprivate int getN(int order) {\n\t\treturn (1-((int)Math.pow(d, order+1)))/(1-d);\n\t}\n\t\n\t/***************************\n\t * Functions for moving upward or downward\n\t **************************/\n\t\n\t//Moves upward\n\tprivate void swim(int i) {\n\t\tif (i > 0 && greater((i-1)/d, i)) {\n\t\t\texch(i, (i-1)/d);\n\t\t\tswim((i-1)/d);\n\t\t}\n\t}\n\t\n\t//Moves downward\n\tprivate void sink(int i) {\n\t\tint child = d*i+1;\n\t\tif (child >= n) return;\n\t\tint min = minChild(i);\n\t\twhile (min < n && greater(i, min)) {\n\t\t\texch(i, min);\n\t\t\ti = min;\n\t\t\tmin = minChild(i);\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Deletes the minimum child\n\t **************************/\n\t\n\t//Return the minimum child of i\n\tprivate int minChild(int i) {\n\t\tint loBound = d*i+1, hiBound = d*i+d;\n\t\tint min = loBound;\n\t\tfor (int cur = loBound; cur <= hiBound; cur++) {\n\t\t\tif (cur < n && greater(min, cur)) min = cur;\n\t\t}\n\t\treturn min;\n\t}\n\t\n\t/***************************\n\t * Resize the priority queue\n\t **************************/\n\t\n\t//Resizes the array containing the keys\n\t//If the heap is full, it adds one floor\n\t//If the heap has two floors empty, it removes one\n\tprivate void resize(int N) {\n\t\tKey[] array = (Key[]) new Comparable[N];\n\t\tfor (int i = 0; i < Math.min(keys.length, array.length); i++) {\n\t\t\tarray[i] = keys[i];\n\t\t\tkeys[i] = null;\n\t\t}\n\t\tkeys = array;\n\t}\n\t\n\t/***************************\n\t * Iterator\n\t **************************/\n\t\n\t/**\n\t * Gets an Iterator over the keys in the priority queue in ascending order\n\t * The Iterator does not implement the remove() method\n\t * iterator() : Worst case is O(n)\n\t * next() : \tWorst case is O(d*log-d(n))\n\t * hasNext() : \tWorst case is O(1)\n\t * @return an Iterator over the keys in the priority queue in ascending order\n\t */\n\t\n\tpublic Iterator<Key> iterator() {\n\t\treturn new MyIterator();\n\t}\n\t\n\t//Constructs an Iterator over the keys in linear time\n\tprivate class MyIterator implements Iterator<Key> {\n\t\tMultiwayMinPQ<Key> data;\n\t\t\n\t\tpublic MyIterator() {\n\t\t\tdata = new MultiwayMinPQ<Key>(comp, d);\n\t\t\tdata.keys = (Key[]) new Comparable[keys.length];\n\t\t\tdata.n = n;\n\t\t\tfor (int i = 0; i < keys.length; i++) {\n\t\t\t\tdata.keys[i] = keys[i];\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean hasNext() {\n\t\t\treturn !data.isEmpty();\n\t\t}\n\t\t\n\t\tpublic Key next() {\n                        if (!hasNext()) throw new NoSuchElementException();\n\t\t\treturn data.delMin();\n\t\t}\n\t\t\n\t\tpublic void remove() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t}\n\t\n\t/***************************\n\t * Comparator\n\t **************************/\n\t\n\t//default Comparator\n\tprivate class MyComparator implements Comparator<Key> {\n\t\t@Override\n\t\tpublic int compare(Key key1, Key key2) {\n\t\t\treturn ((Comparable<Key>) key1).compareTo(key2);\n\t\t}\n\t}\n\t\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/NFA.java",
    "content": "/******************************************************************************\n *  Compilation:  javac NFA.java\n *  Execution:    java NFA regexp text\n *  Dependencies: Stack.java Bag.java Digraph.java DirectedDFS.java\n *\n *  % java NFA \"(A*B|AC)D\" AAAABD\n *  true\n *\n *  % java NFA \"(A*B|AC)D\" AAAAC\n *  false\n *\n *  % java NFA \"(a|(bc)*d)*\" abcbcd\n *  true\n *\n *  % java NFA \"(a|(bc)*d)*\" abcbcbcdaaaabcbcdaaaddd\n *  true\n *\n *  Remarks\n *  -----------\n *  The following features are not supported:\n *    - The + operator\n *    - Multiway or\n *    - Metacharacters in the text\n *    - Character classes.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code NFA} class provides a data type for creating a\n *  <em>nondeterministic finite state automaton</em> (NFA) from a regular\n *  expression and testing whether a given string is matched by that regular\n *  expression.\n *  It supports the following operations: <em>concatenation</em>,\n *  <em>closure</em>, <em>binary or</em>, and <em>parentheses</em>.\n *  It does not support <em>mutiway or</em>, <em>character classes</em>,\n *  <em>metacharacters</em> (either in the text or pattern),\n *  <em>capturing capabilities</em>, <em>greedy</em> or <em>reluctant</em>\n *  modifiers, and other features in industrial-strength implementations\n *  such as {@link java.util.regex.Pattern} and {@link java.util.regex.Matcher}.\n *  <p>\n *  This implementation builds the NFA using a digraph and a stack\n *  and simulates the NFA using digraph search (see the textbook for details).\n *  The constructor takes time proportional to <em>m</em>, where <em>m</em>\n *  is the number of characters in the regular expression.\n *  The <em>recognizes</em> method takes time proportional to <em>m n</em>,\n *  where <em>n</em> is the number of characters in the text.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/54regexp\">Section 5.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class NFA {\n\n    private Digraph graph;     // digraph of epsilon transitions\n    private String regexp;     // regular expression\n    private final int m;       // number of characters in regular expression\n\n    /**\n     * Initializes the NFA from the specified regular expression.\n     *\n     * @param  regexp the regular expression\n     */\n    public NFA(String regexp) {\n        this.regexp = regexp;\n        m = regexp.length();\n        Stack<Integer> ops = new Stack<Integer>();\n        graph = new Digraph(m+1);\n        for (int i = 0; i < m; i++) {\n            int lp = i;\n            if (regexp.charAt(i) == '(' || regexp.charAt(i) == '|')\n                ops.push(i);\n            else if (regexp.charAt(i) == ')') {\n                int or = ops.pop();\n\n                // 2-way or operator\n                if (regexp.charAt(or) == '|') {\n                    lp = ops.pop();\n                    graph.addEdge(lp, or+1);\n                    graph.addEdge(or, i);\n                }\n                else if (regexp.charAt(or) == '(')\n                    lp = or;\n                else assert false;\n            }\n\n            // closure operator (uses 1-character lookahead)\n            if (i < m-1 && regexp.charAt(i+1) == '*') {\n                graph.addEdge(lp, i+1);\n                graph.addEdge(i+1, lp);\n            }\n            if (regexp.charAt(i) == '(' || regexp.charAt(i) == '*' || regexp.charAt(i) == ')')\n                graph.addEdge(i, i+1);\n        }\n        if (ops.size() != 0)\n            throw new IllegalArgumentException(\"Invalid regular expression\");\n    }\n\n    /**\n     * Returns true if the text is matched by the regular expression.\n     *\n     * @param  txt the text\n     * @return {@code true} if the text is matched by the regular expression,\n     *         {@code false} otherwise\n     */\n    public boolean recognizes(String txt) {\n        DirectedDFS dfs = new DirectedDFS(graph, 0);\n        Bag<Integer> pc = new Bag<Integer>();\n        for (int v = 0; v < graph.V(); v++)\n            if (dfs.marked(v)) pc.add(v);\n\n        // Compute possible NFA states for txt[i+1]\n        for (int i = 0; i < txt.length(); i++) {\n            if (txt.charAt(i) == '*' || txt.charAt(i) == '|' || txt.charAt(i) == '(' || txt.charAt(i) == ')')\n                throw new IllegalArgumentException(\"text contains the metacharacter '\" + txt.charAt(i) + \"'\");\n\n            Bag<Integer> match = new Bag<Integer>();\n            for (int v : pc) {\n                if (v == m) continue;\n                if ((regexp.charAt(v) == txt.charAt(i)) || regexp.charAt(v) == '.')\n                    match.add(v+1);\n            }\n            if (match.isEmpty()) continue;\n\n            dfs = new DirectedDFS(graph, match);\n            pc = new Bag<Integer>();\n            for (int v = 0; v < graph.V(); v++)\n                if (dfs.marked(v)) pc.add(v);\n\n            // optimization if no states reachable\n            if (pc.size() == 0) return false;\n        }\n\n        // check for accept state\n        for (int v : pc)\n            if (v == m) return true;\n        return false;\n    }\n\n    /**\n     * Unit tests the {@code NFA} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String regexp = \"(\" + args[0] + \")\";\n        String txt = args[1];\n        NFA nfa = new NFA(regexp);\n        StdOut.println(nfa.recognizes(txt));\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/NonrecursiveDFS.java",
    "content": "/******************************************************************************\n *  Compilation:  javac NonrecursiveDFS.java\n *  Execution:    java NonrecursiveDFS graph.txt s\n *  Dependencies: Graph.java Queue.java Stack.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/tinyCG.txt\n *                https://algs4.cs.princeton.edu/41graph/tinyG.txt\n *                https://algs4.cs.princeton.edu/41graph/mediumG.txt\n *\n *  Run nonrecurisve depth-first search on an undirected graph.\n *  Runs in O(E + V) time using O(V) extra space.\n *\n *  Explores the vertices in exactly the same order as DepthFirstSearch.java.\n *\n *  %  java Graph tinyG.txt\n *  13 vertices, 13 edges\n *  0: 6 2 1 5\n *  1: 0\n *  2: 0\n *  3: 5 4\n *  4: 5 6 3\n *  5: 3 4 0\n *  6: 0 4\n *  7: 8\n *  8: 7\n *  9: 11 10 12\n *  10: 9\n *  11: 9 12\n *  12: 11 9\n *\n *  % java NonrecursiveDFS tinyG.txt 0\n *  0 1 2 3 4 5 6\n *\n * % java NonrecursiveDFS tinyG.txt 9\n * 9 10 11 12\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code NonrecursiveDFS} class represents a data type for finding\n *  the vertices connected to a source vertex <em>s</em> in the undirected\n *  graph.\n *  <p>\n *  This implementation uses a nonrecursive version of depth-first search\n *  with an explicit stack.\n *  See {@link DepthFirstSearch} for the classic recursive version.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the worst\n *  case, where <em>V</em> is the number of vertices and <em>E</em> is the\n *  number of edges.\n *  The {@link #marked(int)} instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the graph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class NonrecursiveDFS {\n    private boolean[] marked;  // marked[v] = is there an s-v path?\n    /**\n     * Computes the vertices connected to the source vertex {@code s} in {@code graph}.\n     * @param graph the graph\n     * @param s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public NonrecursiveDFS(Graph graph, int s) {\n        marked = new boolean[graph.V()];\n\n        validateVertex(s);\n\n        // to be able to iterate over each adjacency list, keeping track of which\n        // vertex in each adjacency list needs to be explored next\n        Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[graph.V()];\n        for (int v = 0; v < graph.V(); v++)\n            adj[v] = graph.adj(v).iterator();\n\n        // depth-first search using an explicit stack\n        Stack<Integer> stack = new Stack<Integer>();\n        marked[s] = true;\n        stack.push(s);\n        while (!stack.isEmpty()) {\n            int v = stack.peek();\n            if (adj[v].hasNext()) {\n                int w = adj[v].next();\n                // StdOut.printf(\"check %d\\n\", w);\n                if (!marked[w]) {\n                    // discovered vertex w for the first time\n                    marked[w] = true;\n                    // edgeTo[w] = v;\n                    stack.push(w);\n                    // StdOut.printf(\"dfs(%d)\\n\", w);\n                }\n            }\n            else {\n                // StdOut.printf(\"%d done\\n\", v);\n                stack.pop();\n            }\n        }\n    }\n\n    /**\n     * Is vertex {@code v} connected to the source vertex {@code s}?\n     * @param v the vertex\n     * @return {@code true} if vertex {@code v} is connected to the source vertex {@code s},\n     *    and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean marked(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code NonrecursiveDFS} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Graph graph = new Graph(in);\n        int s = Integer.parseInt(args[1]);\n        NonrecursiveDFS dfs = new NonrecursiveDFS(graph, s);\n        for (int v = 0; v < graph.V(); v++)\n            if (dfs.marked(v))\n                StdOut.print(v + \" \");\n        StdOut.println();\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/NonrecursiveDirectedDFS.java",
    "content": "/******************************************************************************\n *  Compilation:  javac NonrecursiveDirectedDFS.java\n *  Execution:    java NonrecursiveDirectedDFS digraph.txt s\n *  Dependencies: Digraph.java Queue.java Stack.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Run nonrecurisve depth-first search on a directed graph.\n *  Runs in O(E + V) time.\n *\n *  Explores the vertices in exactly the same order as DirectedDFS.java.\n *\n *\n *  % java NonrecursiveDirectedDFS tinyDG.txt 1\n *  1\n *\n *  % java NonrecursiveDirectedDFS tinyDG.txt 2\n *  0 1 2 3 4 5\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code NonrecursiveDirectedDFS} class represents a data type for finding\n *  the vertices reachable from a source vertex <em>s</em> in the digraph.\n *  <p>\n *  This implementation uses a nonrecursive version of depth-first search\n *  with an explicit stack.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class NonrecursiveDirectedDFS {\n    private boolean[] marked;  // marked[v] = is there an s->v path?\n\n    /**\n     * Computes the vertices reachable from the source vertex {@code s}\n     * in {@code digraph}.\n     * @param  digraph the digraph\n     * @param  s the source vertex\n     * @throws IllegalArgumentException unless {@code 0 <= s < V}\n     */\n    public NonrecursiveDirectedDFS(Digraph digraph, int s) {\n        marked = new boolean[digraph.V()];\n        validateVertex(s);\n\n        // to be able to iterate over each adjacency list, keeping track of which\n        // vertex in each adjacency list needs to be explored next\n        Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            adj[v] = digraph.adj(v).iterator();\n\n        // depth-first search using an explicit stack\n        Stack<Integer> stack = new Stack<Integer>();\n        marked[s] = true;\n        stack.push(s);\n        while (!stack.isEmpty()) {\n            int v = stack.peek();\n            if (adj[v].hasNext()) {\n                int w = adj[v].next();\n                // StdOut.printf(\"check %d\\n\", w);\n                if (!marked[w]) {\n                    // discovered vertex w for the first time\n                    marked[w] = true;\n                    // edgeTo[w] = v;\n                    stack.push(w);\n                    // StdOut.printf(\"dfs(%d)\\n\", w);\n                }\n            }\n            else {\n                // StdOut.printf(\"%d done\\n\", v);\n                stack.pop();\n            }\n        }\n    }\n\n    /**\n     * Is vertex {@code v} reachable from the source vertex {@code s}?\n     * @param  v the vertex\n     * @return {@code true} if vertex {@code v} is reachable from the source vertex {@code s},\n     *         and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public boolean marked(int v) {\n        validateVertex(v);\n        return marked[v];\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code NonrecursiveDirectedDFS} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n        int s = Integer.parseInt(args[1]);\n        NonrecursiveDirectedDFS dfs = new NonrecursiveDirectedDFS(digraph, s);\n        for (int v = 0; v < digraph.V(); v++)\n            if (dfs.marked(v))\n                StdOut.print(v + \" \");\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Out.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Out.java\n *  Execution:    java Out\n *  Dependencies: none\n *\n *  Writes data of various types to: stdout, file, or socket.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.io.OutputStreamWriter;\nimport java.io.PrintWriter;\nimport java.net.Socket;\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Locale;\n\n/**\n *  The <code>Out</code> data type provides methods for writing strings and\n *  numbers to various output streams, including standard output, file, and sockets.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Out {\n\n    // force Unicode UTF-8 encoding; otherwise it's system dependent\n    private static final Charset CHARSET = StandardCharsets.UTF_8;\n\n    // assume language = English, country = US for consistency with In\n    private static final Locale LOCALE = Locale.US;\n\n    private PrintWriter out;\n\n   /**\n     * Initializes an output stream from a {@link OutputStream}.\n     *\n     * @param  os the {@code OutputStream}\n     */\n    public Out(OutputStream os) {\n        OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET);\n        out = new PrintWriter(osw, true);\n    }\n\n   /**\n     * Initializes an output stream from standard output.\n     */\n    public Out() {\n        this(System.out);\n    }\n\n   /**\n     * Initializes an output stream from a socket.\n     *\n     * @param  socket the socket\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if cannot create output stream from socket\n     */\n    public Out(Socket socket) {\n        if (socket == null) {\n            throw new IllegalArgumentException(\"socket argument is null\");\n        }\n        try {\n            OutputStream os = socket.getOutputStream();\n            OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET);\n            out = new PrintWriter(osw, true);\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not create output stream from socket\", e);\n        }\n    }\n\n   /**\n     * Initializes an output stream from a file.\n     *\n     * @param  filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if cannot write the file {@code filename}\n     */\n    public Out(String filename) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename argument is null\");\n        }\n\n        if (filename.length() == 0) {\n            throw new IllegalArgumentException(\"filename argument is the empty string\");\n        }\n\n        try {\n            OutputStream os = new FileOutputStream(filename);\n            OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET);\n            out = new PrintWriter(osw, true);\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not create file '\" + filename + \"' for writing\", e);\n        }\n    }\n\n   /**\n     * Closes the output stream.\n     */\n    public void close() {\n        out.close();\n    }\n\n   /**\n     * Terminates the current line by printing the line-separator string.\n     */\n    public void println() {\n        out.println();\n    }\n\n   /**\n     * Prints an object to this output stream and then terminates the line.\n     *\n     * @param x the object to print\n     */\n    public void println(Object x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a boolean to this output stream and then terminates the line.\n     *\n     * @param x the boolean to print\n     */\n    public void println(boolean x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a character to this output stream and then terminates the line.\n     *\n     * @param x the character to print\n     */\n    public void println(char x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a double to this output stream and then terminates the line.\n     *\n     * @param x the double to print\n     */\n    public void println(double x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a float to this output stream and then terminates the line.\n     *\n     * @param x the float to print\n     */\n    public void println(float x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints an integer to this output stream and then terminates the line.\n     *\n     * @param x the integer to print\n     */\n    public void println(int x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a long to this output stream and then terminates the line.\n     *\n     * @param x the long to print\n     */\n    public void println(long x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a byte to this output stream and then terminates the line.\n     * <p>\n     * To write binary data, see {@link BinaryOut}.\n     *\n     * @param x the byte to print\n     */\n    public void println(byte x) {\n        out.println(x);\n    }\n\n\n\n   /**\n     * Flushes this output stream.\n     */\n    public void print() {\n        out.flush();\n    }\n\n   /**\n     * Prints an object to this output stream and flushes this output stream.\n     *\n     * @param x the object to print\n     */\n    public void print(Object x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a boolean to this output stream and flushes this output stream.\n     *\n     * @param x the boolean to print\n     */\n    public void print(boolean x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a character to this output stream and flushes this output stream.\n     *\n     * @param x the character to print\n     */\n    public void print(char x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a double to this output stream and flushes this output stream.\n     *\n     * @param x the double to print\n     */\n    public void print(double x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a float to this output stream and flushes this output stream.\n     *\n     * @param x the float to print\n     */\n    public void print(float x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints an integer to this output stream and flushes this output stream.\n     *\n     * @param x the integer to print\n     */\n    public void print(int x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a long integer to this output stream and flushes this output stream.\n     *\n     * @param x the long integer to print\n     */\n    public void print(long x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a byte to this output stream and flushes this output stream.\n     *\n     * @param x the byte to print\n     */\n    public void print(byte x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a formatted string to this output stream, using the specified format\n     * string and arguments, and then flushes this output stream.\n     *\n     * @param format the format string\n     * @param args   the arguments accompanying the format string\n     */\n    public void printf(String format, Object... args) {\n        out.printf(LOCALE, format, args);\n        out.flush();\n    }\n\n   /**\n     * Prints a formatted string to this output stream, using the specified\n     * locale, format string, and arguments, and then flushes this output stream.\n     *\n     * @param locale the locale\n     * @param format the format string\n     * @param args   the arguments accompanying the format string\n     */\n    public void printf(Locale locale, String format, Object... args) {\n        out.printf(locale, format, args);\n        out.flush();\n    }\n\n\n   /**\n     * A test client.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Out out;\n\n        // write to stdout\n        out = new Out();\n        out.println(\"Test 1\");\n        out.close();\n\n        // write to a file\n        out = new Out(\"test.txt\");\n        out.println(\"Test 2\");\n        out.close();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Particle.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Particle.java\n *  Execution:    none\n *  Dependencies: StdDraw.java\n *\n *  A particle moving in the unit box with a given position, velocity,\n *  radius, and mass.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.Color;\n\n/**\n *  The {@code Particle} class represents a particle moving in the unit box,\n *  with a given position, velocity, radius, and mass. Methods are provided\n *  for moving the particle and for predicting and resolvling elastic\n *  collisions with vertical walls, horizontal walls, and other particles.\n *  This data type is mutable because the position and velocity change.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/61event\">Section 6.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Particle {\n    private static final double INFINITY = Double.POSITIVE_INFINITY;\n\n    private double rx, ry;        // position\n    private double vx, vy;        // velocity\n    private int count;            // number of collisions so far\n    private final double radius;  // radius\n    private final double mass;    // mass\n    private final Color color;    // color\n\n\n    /**\n     * Initializes a particle with the specified position, velocity, radius, mass, and color.\n     *\n     * @param  rx <em>x</em>-coordinate of position\n     * @param  ry <em>y</em>-coordinate of position\n     * @param  vx <em>x</em>-coordinate of velocity\n     * @param  vy <em>y</em>-coordinate of velocity\n     * @param  radius the radius\n     * @param  mass the mass\n     * @param  color the color\n     */\n    public Particle(double rx, double ry, double vx, double vy, double radius, double mass, Color color) {\n        if (!(radius > 0.0)) throw new IllegalArgumentException(\"radius must be positive\");\n        if (!(mass > 0.0)) throw new IllegalArgumentException(\"mass must be positive\");\n        if (rx - radius < -1.0 || rx + radius > 1.0) throw new IllegalArgumentException(\"out-of-bounds rx\");\n        if (ry - radius < -1.0 || ry + radius > 1.0) throw new IllegalArgumentException(\"out-of-bounds ry\");\n        this.vx = vx;\n        this.vy = vy;\n        this.rx = rx;\n        this.ry = ry;\n        this.radius = radius;\n        this.mass   = mass;\n        this.color  = color;\n    }\n\n    /**\n     * Initializes a particle with a random position and velocity.\n     * The position is uniform in the unit box; the velocity in\n     * either direciton is chosen uniformly at random.\n     */\n    public Particle() {\n        rx     = StdRandom.uniformDouble(0.0, 1.0);\n        ry     = StdRandom.uniformDouble(0.0, 1.0);\n        vx     = StdRandom.uniformDouble(-0.005, 0.005);\n        vy     = StdRandom.uniformDouble(-0.005, 0.005);\n        radius = 0.02;\n        mass   = 0.5;\n        color  = Color.BLACK;\n    }\n\n    /**\n     * Moves this particle in a straight line (based on its velocity)\n     * for the specified amount of time.\n     *\n     * @param  dt the amount of time\n     */\n    public void move(double dt) {\n        rx += vx * dt;\n        ry += vy * dt;\n    }\n\n    /**\n     * Draws this particle to standard draw.\n     */\n    public void draw() {\n        StdDraw.setPenColor(color);\n        StdDraw.filledCircle(rx, ry, radius);\n    }\n\n    /**\n     * Returns the number of collisions involving this particle with\n     * vertical walls, horizontal walls, or other particles.\n     * This is equal to the number of calls to {@link #bounceOff},\n     * {@link #bounceOffVerticalWall}, and\n     * {@link #bounceOffHorizontalWall}.\n     *\n     * @return the number of collisions involving this particle with\n     *         vertical walls, horizontal walls, or other particles\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Returns the amount of time for this particle to collide with the specified\n     * particle, assuming no interening collisions.\n     *\n     * @param  that the other particle\n     * @return the amount of time for this particle to collide with the specified\n     *         particle, assuming no interening collisions;\n     *         {@code Double.POSITIVE_INFINITY} if the particles will not collide\n     */\n    public double timeToHit(Particle that) {\n        if (this == that) return INFINITY;\n        double dx  = that.rx - this.rx;\n        double dy  = that.ry - this.ry;\n        double dvx = that.vx - this.vx;\n        double dvy = that.vy - this.vy;\n        double dvdr = dx*dvx + dy*dvy;\n        if (dvdr > 0) return INFINITY;\n        double dvdv = dvx*dvx + dvy*dvy;\n        if (dvdv == 0) return INFINITY;\n        double drdr = dx*dx + dy*dy;\n        double sigma = this.radius + that.radius;\n         double d = (dvdr*dvdr) - dvdv * (drdr - sigma*sigma);\n        // if (drdr < sigma*sigma) StdOut.println(\"overlapping particles\");\n        if (d < 0) return INFINITY;\n        double t = -(dvdr + Math.sqrt(d)) / dvdv;\n\n        // should't happen, but seems to be needed for some extreme inputs\n        // (floating-point precision when dvdv is close to 0, I think)\n        if (t <= 0) return INFINITY;\n\n        return t;\n    }\n\n    /**\n     * Returns the amount of time for this particle to collide with a vertical\n     * wall, assuming no interening collisions.\n     *\n     * @return the amount of time for this particle to collide with a vertical wall,\n     *         assuming no interening collisions;\n     *         {@code Double.POSITIVE_INFINITY} if the particle will not collide\n     *         with a vertical wall\n     */\n    public double timeToHitVerticalWall() {\n        if      (vx > 0) return (1.0 - rx - radius) / vx;\n        else if (vx < 0) return (radius - rx) / vx;\n        else             return INFINITY;\n    }\n\n    /**\n     * Returns the amount of time for this particle to collide with a horizontal\n     * wall, assuming no interening collisions.\n     *\n     * @return the amount of time for this particle to collide with a horizontal wall,\n     *         assuming no interening collisions;\n     *         {@code Double.POSITIVE_INFINITY} if the particle will not collide\n     *         with a horizontal wall\n     */\n    public double timeToHitHorizontalWall() {\n        if      (vy > 0) return (1.0 - ry - radius) / vy;\n        else if (vy < 0) return (radius - ry) / vy;\n        else             return INFINITY;\n    }\n\n    /**\n     * Updates the velocities of this particle and the specified particle according\n     * to the laws of elastic collision. Assumes that the particles are colliding\n     * at this instant.\n     *\n     * @param  that the other particle\n     */\n    public void bounceOff(Particle that) {\n        double dx  = that.rx - this.rx;\n        double dy  = that.ry - this.ry;\n        double dvx = that.vx - this.vx;\n        double dvy = that.vy - this.vy;\n        double dvdr = dx*dvx + dy*dvy;             // dv dot dr\n        double dist = this.radius + that.radius;   // distance between particle centers at collison\n\n        // magnitude of normal force\n        double magnitude = 2 * this.mass * that.mass * dvdr / ((this.mass + that.mass) * dist);\n\n        // normal force, and in x and y directions\n        double fx = magnitude * dx / dist;\n        double fy = magnitude * dy / dist;\n\n        // update velocities according to normal force\n        this.vx += fx / this.mass;\n        this.vy += fy / this.mass;\n        that.vx -= fx / that.mass;\n        that.vy -= fy / that.mass;\n\n        // update collision counts\n        this.count++;\n        that.count++;\n    }\n\n    /**\n     * Updates the velocity of this particle upon collision with a vertical\n     * wall (by reflecting the velocity in the <em>x</em>-direction).\n     * Assumes that the particle is colliding with a vertical wall at this instant.\n     */\n    public void bounceOffVerticalWall() {\n        vx = -vx;\n        count++;\n    }\n\n    /**\n     * Updates the velocity of this particle upon collision with a horizontal\n     * wall (by reflecting the velocity in the <em>y</em>-direction).\n     * Assumes that the particle is colliding with a horizontal wall at this instant.\n     */\n    public void bounceOffHorizontalWall() {\n        vy = -vy;\n        count++;\n    }\n\n    /**\n     * Returns the kinetic energy of this particle.\n     * The kinetic energy is given by the formula 1/2 <em>m</em> <em>v</em><sup>2</sup>,\n     * where <em>m</em> is the mass of this particle and <em>v</em> is its velocity.\n     *\n     * @return the kinetic energy of this particle\n     */\n    public double kineticEnergy() {\n        return 0.5 * mass * (vx*vx + vy*vy);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/PatriciaSET.java",
    "content": "/******************************************************************************\n *  Compilation:  javac PatriciaSET.java\n *  Execution:    java PatriciaSET\n *  Dependencies: StdOut.java StdRandom.java Queue.java\n *  Data files:   n/a\n *\n *  A set implementation based on PATRICIA.\n *\n *  % java PatriciaSET 1000000 1\n *  Creating dataset (1000000 items)...\n *  Shuffling...\n *  Adding (1000000 items)...\n *  Iterating...\n *  1000000 items iterated\n *  Shuffling...\n *  Deleting (500000 items)...\n *  Iterating...\n *  500000 items iterated\n *  Checking...\n *  500000 items found and 500000 (deleted) items missing\n *  Deleting the rest (500000 items)...\n *  PASS 1 TESTS SUCCEEDED\n *  %\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code PatriciaSET} class provides an implementation of an\n *  unordered set, with the restriction that the items (keys) are of class\n *  {@link java.lang.String}. It supports the usual <em>add</em>,\n *  <em>contains</em>, <em>delete</em>, <em>size</em>, and <em>is-empty</em>\n *  methods. It also provides an <em>iterator</em> method for iterating over all\n *  the elements in the set.\n *  <p>\n *  This unordered set class implements PATRICIA (Practical Algorithm to\n *  Retrieve Information Coded In Alphanumeric). In spite of the acronym, string\n *  keys are not limited to alphanumeric content. A key may possess any string\n *  value, with one exception: a zero-length string is not permitted.\n *  <p>\n *  Unlike other generic set implementations that can accept a parameterized key\n *  type, this set class can only accommodate keys of class\n *  {@link java.lang.String}. This unfortunate restriction stems from a\n *  limitation in Java. Although Java provides excellent support for generic\n *  programming, the current infrastructure somewhat limits generic collection\n *  implementations to those that employ comparison-based or hash-based methods.\n *  PATRICIA does not employ comparisons or hashing; instead, it relies on\n *  bit-test operations. Because Java does not furnish any generic abstractions\n *  (or implementations) for bit-testing the contents of an object, providing\n *  support for generic keys using PATRICIA does not seem practical.\n *  <p>\n *  PATRICIA is a variation of a trie, and it is often classified as a\n *  space-optimized trie. In a classical trie, each level represents a\n *  subsequent digit in a key. In PATRICIA, nodes only exist to identify the\n *  digits (bits) that distinguish the individual keys within the trie. Because\n *  PATRICIA uses a radix of two, each node has only two children, like a binary\n *  tree. Also like a binary tree, the number of nodes, within the trie, equals\n *  the number of keys. Consequently, some classify PATRICIA as a tree.\n *  <p>\n *  The analysis of PATRICIA is complicated. The theoretical wost-case\n *  performance for an <em>add</em>, <em>contains</em>, or <em>delete</em>\n *  operation is <strong>O(N)</strong>, when <strong>N</strong> is less than\n *  <strong>W</strong> (where <strong>W</strong> is the length in bits of the\n *  longest key), and <strong>O(W)</strong>, when <strong>N</strong> is greater\n *  than <strong>W</strong>. However, the worst case is unlikely to occur with\n *  typical use. The average (and usual) performance of PATRICIA is\n *  approximately <strong>~lg N</strong> for each <em>add</em>,\n *  <em>contains</em>, or <em>delete</em> operation. Although this appears to\n *  put PATRICIA on the same footing as binary trees, this time complexity\n *  represents the number of single-bit test operations (under PATRICIA), and\n *  not full-key comparisons (as required by binary trees). After the single-bit\n *  tests conclude, PATRICIA requires just one full-key comparison to confirm\n *  the existence (or absence) of the key (per <em>add</em>, <em>contains</em>,\n *  or <em>delete</em> operation).\n *  <p>\n *  In practice, decent implementations of PATRICIA can often outperform\n *  balanced binary trees, and even hash tables. Although this particular\n *  implementation performs well, the source code was written with an emphasis\n *  on clarity, and not performance. PATRICIA performs admirably when its\n *  bit-testing loops are well tuned. Consider using the source code as a guide,\n *  should you need to produce an optimized implementation, for another key type,\n *  or in another programming language.\n *  <p>\n *  Other resources for PATRICIA:<br>\n *  Sedgewick, R. (1990) <i>Algorithms in C</i>, Addison-Wesley<br>\n *  Knuth, D. (1973) <i>The Art of Computer Programming</i>, Addison-Wesley<br>\n *\n *  @author John Hentosh (based on an implementation by Robert Sedgewick)\n */\npublic class PatriciaSET implements Iterable<String> {\n    private Node head;\n    private int count;\n\n    /* An inner Node class specifies the objects that hold each key. The b\n     * value indicates the relevant bit position.\n     */\n    private class Node {\n        private Node left, right;\n        private String key;\n        private int b;\n\n        public Node(String key, int b) {\n            this.key = key;\n            this.b = b;\n        }\n    };\n\n    /**\n     * Initializes an empty PATRICIA-based set.\n     */\n    /* The constructor creates a head (sentinel) node that contains a\n     * zero-length string.\n     */\n    public PatriciaSET() {\n        head = new Node(\"\", 0);\n        head.left = head;\n        head.right = head;\n        count = 0;\n    }\n\n    /**\n     * Adds the key to the set if it is not already present.\n     * @param key the key to add\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public void add(String key) {\n        if (key == null) throw new IllegalArgumentException(\"called add(null)\");\n        if (key.length() == 0) throw new IllegalArgumentException(\"invalid key\");\n        Node p;\n        Node x = head;\n        do {\n            p = x;\n            if (safeBitTest(key, x.b)) x = x.right;\n            else                       x = x.left;\n        } while (p.b < x.b);\n        if (!x.key.equals(key)) {\n            int b = firstDifferingBit(x.key, key);\n            x = head;\n            do {\n                p = x;\n                if (safeBitTest(key, x.b)) x = x.right;\n                else                       x = x.left;\n            } while (p.b < x.b && x.b < b);\n            Node t = new Node(key, b);\n            if (safeBitTest(key, b)) {\n                t.left  = x;\n                t.right = t;\n            }\n            else {\n                t.left  = t;\n                t.right = x;\n            }\n            if (safeBitTest(key, p.b)) p.right = t;\n            else                       p.left = t;\n            count++;\n        }\n    }\n\n    /**\n     * Does the set contain the given key?\n     * @param key the key\n     * @return {@code true} if the set contains {@code key} and\n     * {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public boolean contains(String key) {\n        if (key == null) throw new IllegalArgumentException(\"called contains(null)\");\n        if (key.length() == 0) throw new IllegalArgumentException(\"invalid key\");\n        Node p;\n        Node x = head;\n        do {\n            p = x;\n            if (safeBitTest(key, x.b)) x = x.right;\n            else                       x = x.left;\n        } while (p.b < x.b);\n        return x.key.equals(key);\n    }\n\n    /**\n     * Removes the key from the set if the key is present.\n     * @param key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public void delete(String key) {\n        if (key == null) throw new IllegalArgumentException(\"called delete(null)\");\n        if (key.length() == 0) throw new IllegalArgumentException(\"invalid key\");\n        Node g;             // previous previous (grandparent)\n        Node p = head;      // previous (parent)\n        Node x = head;      // node to delete\n        do {\n            g = p;\n            p = x;\n            if (safeBitTest(key, x.b)) x = x.right;\n            else                       x = x.left;\n        } while (p.b < x.b);\n        if (x.key.equals(key)) {\n            Node z;\n            Node y = head;\n            do {            // find the true parent (z) of x\n                z = y;\n                if (safeBitTest(key, y.b)) y = y.right;\n                else                       y = y.left;\n            } while (y != x);\n            if (x == p) {   // case 1: remove (leaf node) x\n                Node c;     // child of x\n                if (safeBitTest(key, x.b)) c = x.left;\n                else                       c = x.right;\n                if (safeBitTest(key, z.b)) z.right = c;\n                else                       z.left  = c;\n            }\n            else {          // case 2: p replaces (internal node) x\n                Node c;     // child of p\n                if (safeBitTest(key, p.b)) c = p.left;\n                else                       c = p.right;\n                if (safeBitTest(key, g.b)) g.right = c;\n                else                       g.left  = c;\n                if (safeBitTest(key, z.b)) z.right = p;\n                else                       z.left  = p;\n                p.left = x.left;\n                p.right = x.right;\n                p.b = x.b;\n            }\n            count--;\n        }\n    }\n\n    /**\n     * Is the set empty?\n     * @return {@code true} if the set is empty, and {@code false}\n     * otherwise\n     */\n    boolean isEmpty() {\n        return count == 0;\n    }\n\n    /**\n     * Returns the number of keys in the set.\n     * @return the number of keys in the set\n     */\n    int size() {\n        return count;\n    }\n\n    /**\n     * Returns all of the keys in the set, as an iterator.\n     * To iterate over all of the keys in a set named {@code set}, use the\n     * foreach notation: {@code for (Key key : set)}.\n     * @return an iterator to all of the keys in the set\n     */\n    public Iterator<String> iterator() {\n        Queue<String> queue = new Queue<String>();\n        if (head.left  != head) collect(head.left,  0, queue);\n        if (head.right != head) collect(head.right, 0, queue);\n        return queue.iterator();\n    }\n\n    private void collect(Node x, int b, Queue<String> queue) {\n        if (x.b > b) {\n            collect(x.left, x.b, queue);\n            queue.enqueue(x.key);\n            collect(x.right, x.b, queue);\n        }\n    }\n\n    /**\n     * Returns a string representation of this set.\n     * @return a string representation of this set, with the keys separated\n     * by single spaces\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (String key : this) s.append(key + \" \");\n        if (s.length() > 0) s.deleteCharAt(s.length() - 1);\n        return s.toString();\n    }\n\n    /* The safeBitTest function logically appends a terminating sequence (when\n     * required) to extend (logically) the string beyond its length.\n     *\n     * The inner loops of the get and put methods flow much better when they\n     * are not concerned with the lengths of strings, so a trick is employed to\n     * allow the get and put methods to view every string as an \"infinite\"\n     * sequence of bits. Logically, every string gets a '\\uffff' character,\n     * followed by an \"infinite\" sequence of '\\u0000' characters, appended to\n     * the end.\n     *\n     * Note that the '\\uffff' character serves to mark the end of the string,\n     * and it is necessary. Simply padding with '\\u0000' is insufficient to\n     * make all unique Unicode strings \"look\" unique to the get and put methods\n     * (because these methods do not regard string lengths).\n     */\n    private static boolean safeBitTest(String key, int b) {\n        if (b < key.length() * 16)      return bitTest(key, b) != 0;\n        if (b > key.length() * 16 + 15) return false;   // padding\n        /* 16 bits of 0xffff */         return true;    // end marker\n    }\n\n    private static int bitTest(String key, int b) {\n        return (key.charAt(b >>> 4) >>> (b & 0xf)) & 1;\n    }\n\n    /* Like the safeBitTest function, the safeCharAt function makes every\n     * string look like an \"infinite\" sequence of characters. Logically, every\n     * string gets a '\\uffff' character, followed by an \"infinite\" sequence of\n     * '\\u0000' characters, appended to the end.\n     */\n    private static int safeCharAt(String key, int i) {\n        if (i < key.length()) return key.charAt(i);\n        if (i > key.length()) return 0x0000;            // padding\n        else                  return 0xffff;            // end marker\n    }\n\n    /* For efficiency's sake, the firstDifferingBit function compares entire\n     * characters first, and then considers the individual bits (once it finds\n     * two characters that do not match). Also, the least significant bits of\n     * an individual character are examined first. There are many Unicode\n     * alphabets where most (if not all) of the \"action\" occurs in the least\n     * significant bits.\n     *\n     * Notice that the very first character comparison excludes the\n     * least-significant bit. The firstDifferingBit function must never return\n     * zero; otherwise, a node would become created as a child to the head\n     * (sentinel) node that matches the bit-index value (zero) stored in the\n     * head node. This would violate the invariant that bit-index values\n     * increase as you descend into the trie.\n     */\n    private static int firstDifferingBit(String k1, String k2) {\n        int i = 0;\n        int c1 = safeCharAt(k1, 0) & ~1;\n        int c2 = safeCharAt(k2, 0) & ~1;\n        if (c1 == c2) {\n            i = 1;\n            while (safeCharAt(k1, i) == safeCharAt(k2, i)) i++;\n            c1 = safeCharAt(k1, i);\n            c2 = safeCharAt(k2, i);\n        }\n        int b = 0;\n        while (((c1 >>> b) & 1) == ((c2 >>> b) & 1)) b++;\n        return i * 16 + b;\n    }\n\n    /**\n     * Unit tests the {@code PatriciaSET} data type.\n     * This test fixture runs a series of tests on a randomly generated dataset.\n     * You may specify up to two integer parameters on the command line. The\n     * first parameter indicates the size of the dataset. The second parameter\n     * controls the number of passes (a new random dataset becomes generated at\n     * the start of each pass).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        PatriciaSET set = new PatriciaSET();\n        int limitItem = 1000000;\n        int limitPass = 1;\n        int countPass = 0;\n        boolean ok = true;\n\n        if (args.length > 0) limitItem = Integer.parseInt(args[0]);\n        if (args.length > 1) limitPass = Integer.parseInt(args[1]);\n\n        do {\n            String[] a = new String[limitItem];\n\n            StdOut.printf(\"Creating dataset (%d items)...\\n\", limitItem);\n            for (int i = 0; i < limitItem; i++)\n                a[i] = Integer.toString(i, 16);\n\n            StdOut.printf(\"Shuffling...\\n\");\n            StdRandom.shuffle(a);\n\n            StdOut.printf(\"Adding (%d items)...\\n\", limitItem);\n            for (int i = 0; i < limitItem; i++)\n                set.add(a[i]);\n\n            int countItems = 0;\n            StdOut.printf(\"Iterating...\\n\");\n            for (String key : set) countItems++;\n            StdOut.printf(\"%d items iterated\\n\", countItems);\n            if (countItems != limitItem)  ok = false;\n            if (countItems != set.size()) ok = false;\n\n            StdOut.printf(\"Shuffling...\\n\");\n            StdRandom.shuffle(a);\n\n            int limitDelete = limitItem / 2;\n            StdOut.printf(\"Deleting (%d items)...\\n\", limitDelete);\n            for (int i = 0; i < limitDelete; i++)\n                set.delete(a[i]);\n\n            countItems = 0;\n            StdOut.printf(\"Iterating...\\n\");\n            for (String key : set) countItems++;\n            StdOut.printf(\"%d items iterated\\n\", countItems);\n            if (countItems != limitItem - limitDelete) ok = false;\n            if (countItems != set.size())              ok = false;\n\n            int countDelete = 0;\n            int countRemain = 0;\n            StdOut.printf(\"Checking...\\n\");\n            for (int i = 0; i < limitItem; i++) {\n                if (i < limitDelete) {\n                    if (!set.contains(a[i])) countDelete++;\n                }\n                else {\n                    if (set.contains(a[i])) countRemain++;\n                }\n            }\n            StdOut.printf(\"%d items found and %d (deleted) items missing\\n\",\n                countRemain, countDelete);\n            if (countRemain + countDelete != limitItem)  ok = false;\n            if (countRemain               != set.size()) ok = false;\n            if (set.isEmpty())                           ok = false;\n\n            StdOut.printf(\"Deleting the rest (%d items)...\\n\",\n                limitItem - countDelete);\n            for (int i = countDelete; i < limitItem; i++)\n                set.delete(a[i]);\n            if (!set.isEmpty()) ok = false;\n\n            countPass++;\n            if (ok) StdOut.printf(\"PASS %d TESTS SUCCEEDED\\n\", countPass);\n            else    StdOut.printf(\"PASS %d TESTS FAILED\\n\",    countPass);\n        } while (ok && countPass < limitPass);\n\n        if (!ok) throw new java.lang.RuntimeException(\"TESTS FAILED\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/PatriciaST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac PatriciaST.java\n *  Execution:    java PatriciaST\n *  Dependencies: StdOut.java StdRandom.java Queue.java\n *  Data files:   n/a\n *\n *  A symbol table implementation based on PATRICIA.\n *\n *  % java PatriciaST 1000000 1\n *  Creating dataset (1000000 items)...\n *  Shuffling...\n *  Adding (1000000 items)...\n *  Iterating...\n *  1000000 items iterated\n *  Shuffling...\n *  Deleting (500000 items)...\n *  Iterating...\n *  500000 items iterated\n *  Checking...\n *  500000 items found and 500000 (deleted) items missing\n *  Deleting the rest (500000 items)...\n *  PASS 1 TESTS SUCCEEDED\n *  %\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code PatriciaST} class provides an implementation of an unordered\n *  symbol table of key-value pairs, with the restriction that the key is of\n *  class {@link java.lang.String}. It supports the usual <em>put</em>,\n *  <em>get</em>, <em>contains</em>, <em>delete</em>, <em>size</em>, and\n *  <em>is-empty</em> methods. It also provides a <em>keys</em> method for\n *  iterating over all of the keys. A symbol table implements the\n *  <em>associative array</em> abstraction: when associating a value with a key\n *  that is already in the symbol table, the convention is to replace the old\n *  value with the new value. Unlike {@link java.util.Map}, this class uses the\n *  convention that values cannot be {@code null}—setting the value\n *  associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  This unordered symbol table class implements PATRICIA (Practical Algorithm\n *  to Retrieve Information Coded In Alphanumeric). In spite of the acronym,\n *  string keys are not limited to alphanumeric content. A key may possess any\n *  string value, except for the string of zero length (the empty string).\n *  <p>\n *  Unlike other generic symbol table implementations that can accept a\n *  parameterized key type, this symbol table class can only accommodate keys\n *  of class {@link java.lang.String}. This unfortunate restriction stems from a\n *  limitation in Java. Although Java provides excellent support for generic\n *  programming, the current infrastructure somewhat limits generic collection\n *  implementations to those that employ comparison-based or hash-based methods.\n *  PATRICIA does not employ comparisons or hashing; instead, it relies on\n *  bit-test operations. Because Java does not furnish any generic abstractions\n *  (or implementations) for bit-testing the contents of an object, providing\n *  support for generic keys using PATRICIA does not seem practical.\n *  <p>\n *  PATRICIA is a variation of a trie, and it is often classified as a\n *  space-optimized trie. In a classical trie, each level represents a\n *  subsequent digit in a key. In PATRICIA, nodes only exist to identify the\n *  digits (bits) that distinguish the individual keys within the trie. Because\n *  PATRICIA uses a radix of two, each node has only two children, like a binary\n *  tree. Also like a binary tree, the number of nodes, within the trie, equals\n *  the number of keys. Consequently, some classify PATRICIA as a tree.\n *  <p>\n *  The analysis of PATRICIA is complicated. The theoretical wost-case\n *  performance for a <em>get</em>, <em>put</em>, or <em>delete</em> operation\n *  is <strong>O(N)</strong>, when <strong>N</strong> is less than\n *  <strong>W</strong> (where <strong>W</strong> is the length in bits of the\n *  longest key), and <strong>O(W)</strong>, when <strong>N</strong> is greater\n *  than <strong>W</strong>. However, the worst case is unlikely to occur with\n *  typical use. The average (and usual) performance of PATRICIA is\n *  approximately <strong>~lg N</strong> for each <em>get</em>, <em>put</em>, or\n *  <em>delete</em> operation. Although this appears to put PATRICIA on the same\n *  footing as binary trees, this time complexity represents the number of\n *  single-bit test operations (under PATRICIA), and not full-key comparisons\n *  (as required by binary trees). After the single-bit tests conclude, PATRICIA\n *  requires just one full-key comparison to confirm the existence (or absence)\n *  of the key (per <em>get</em>, <em>put</em>, or <em>delete</em> operation).\n *  <p>\n *  In practice, decent implementations of PATRICIA can often outperform\n *  balanced binary trees, and even hash tables. Although this particular\n *  implementation performs well, the source code was written with an emphasis\n *  on clarity, and not performance. PATRICIA performs admirably when its\n *  bit-testing loops are well tuned. Consider using the source code as a guide,\n *  should you need to produce an optimized implementation, for another key type,\n *  or in another programming language.\n *  <p>\n *  Other resources for PATRICIA:<br>\n *  Sedgewick, R. (1990) <i>Algorithms in C</i>, Addison-Wesley<br>\n *  Knuth, D. (1973) <i>The Art of Computer Programming</i>, Addison-Wesley<br>\n *\n *  @author John Hentosh (based on an implementation by Robert Sedgewick)\n */\npublic class PatriciaST<Value> {\n    private Node head;\n    private int count;\n\n    /* An inner Node class specifies the objects that hold each key-value pair.\n     * The b value indicates the relevant bit position.\n     */\n    private class Node {\n        private Node left, right;\n        private String key;\n        private Value val;\n        private int b;\n\n        public Node(String key, Value val, int b) {\n            this.key = key;\n            this.val = val;\n            this.b = b;\n        }\n    };\n\n    /**\n     * Initializes an empty PATRICIA-based symbol table.\n     */\n    /* The constructor creates a head (sentinel) node that contains a\n     * zero-length string.\n     */\n    public PatriciaST() {\n        head = new Node(\"\", null, 0);\n        head.left = head;\n        head.right = head;\n        count = 0;\n    }\n\n    /**\n     * Places a key-value pair into the symbol table. If the table already\n     * contains the specified key, then its associated value becomes updated.\n     * If the value provided is {@code null}, then the key becomes removed\n     * from the symbol table.\n     * @param key the key\n     * @param val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public void put(String key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"called put(null)\");\n        if (key.length() == 0) throw new IllegalArgumentException(\"invalid key\");\n        if (val == null) delete(key);\n        Node p;\n        Node x = head;\n        do {\n            p = x;\n            if (safeBitTest(key, x.b)) x = x.right;\n            else                       x = x.left;\n        } while (p.b < x.b);\n        if (!x.key.equals(key)) {\n            int b = firstDifferingBit(x.key, key);\n            x = head;\n            do {\n                p = x;\n                if (safeBitTest(key, x.b)) x = x.right;\n                else                       x = x.left;\n            } while (p.b < x.b && x.b < b);\n            Node t = new Node(key, val, b);\n            if (safeBitTest(key, b)) {\n                t.left  = x;\n                t.right = t;\n            }\n            else {\n                t.left  = t;\n                t.right = x;\n            }\n            if (safeBitTest(key, p.b)) p.right = t;\n            else                       p.left  = t;\n            count++;\n        }\n        else x.val = val;\n    }\n\n    /**\n     * Retrieves the value associated with the given key.\n     * @param key the key\n     * @return the value associated with the given key if the key is in the\n     * symbol table and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public Value get(String key) {\n        if (key == null) throw new IllegalArgumentException(\"called get(null)\");\n        if (key.length() == 0) throw new IllegalArgumentException(\"invalid key\");\n        Node p;\n        Node x = head;\n        do {\n            p = x;\n            if (safeBitTest(key, x.b)) x = x.right;\n            else                       x = x.left;\n        } while (p.b < x.b);\n        if (x.key.equals(key)) return x.val;\n        else                   return null;\n    }\n\n    /**\n     * Removes a key and its associated value from the symbol table, if it\n     * exists.\n     * @param key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public void delete(String key) {\n        if (key == null) throw new IllegalArgumentException(\"called delete(null)\");\n        if (key.length() == 0) throw new IllegalArgumentException(\"invalid key\");\n        Node g;             // previous previous (grandparent)\n        Node p = head;      // previous (parent)\n        Node x = head;      // node to delete\n        do {\n            g = p;\n            p = x;\n            if (safeBitTest(key, x.b)) x = x.right;\n            else                       x = x.left;\n        } while (p.b < x.b);\n        if (x.key.equals(key)) {\n            Node z;\n            Node y = head;\n            do {            // find the true parent (z) of x\n                z = y;\n                if (safeBitTest(key, y.b)) y = y.right;\n                else                       y = y.left;\n            } while (y != x);\n            if (x == p) {   // case 1: remove (leaf node) x\n                Node c;     // child of x\n                if (safeBitTest(key, x.b)) c = x.left;\n                else                       c = x.right;\n                if (safeBitTest(key, z.b)) z.right = c;\n                else                       z.left  = c;\n            }\n            else {          // case 2: p replaces (internal node) x\n                Node c;     // child of p\n                if (safeBitTest(key, p.b)) c = p.left;\n                else                       c = p.right;\n                if (safeBitTest(key, g.b)) g.right = c;\n                else                       g.left  = c;\n                if (safeBitTest(key, z.b)) z.right = p;\n                else                       z.left  = p;\n                p.left = x.left;\n                p.right = x.right;\n                p.b = x.b;\n            }\n            count--;\n        }\n    }\n\n    /**\n     * Returns {@code true} if the key-value pair, specified by the given\n     * key, exists within the symbol table.\n     * @param key the key\n     * @return {@code true} if this symbol table contains the given\n     * {@code key} and {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws IllegalArgumentException if {@code key} is the empty string.\n     */\n    public boolean contains(String key) {\n        return get(key) != null;\n    }\n\n    /**\n     * Returns {@code true} if the symbol table is empty.\n     * @return {@code true} if this symbol table is empty and\n     * {@code false} otherwise\n     */\n    boolean isEmpty() {\n        return count == 0;\n    }\n\n    /**\n     * Returns the number of key-value pairs within the symbol table.\n     * @return the number of key-value pairs within this symbol table\n     */\n    int size() {\n        return count;\n    }\n\n    /**\n     * Returns all keys in the symbol table as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named\n     * {@code st}, use the foreach notation:\n     * {@code for (Key key : st.keys())}.\n     * @return all keys in the symbol table as an {@code Iterable}\n     */\n    public Iterable<String> keys() {\n        Queue<String> queue = new Queue<String>();\n        if (head.left  != head) keys(head.left,  0, queue);\n        if (head.right != head) keys(head.right, 0, queue);\n        return queue;\n    }\n\n    private void keys(Node x, int b, Queue<String> queue) {\n        if (x.b > b) {\n            keys(x.left, x.b, queue);\n            queue.enqueue(x.key);\n            keys(x.right, x.b, queue);\n        }\n    }\n\n    /* The safeBitTest function logically appends a terminating sequence (when\n     * required) to extend (logically) the string beyond its length.\n     *\n     * The inner loops of the get and put methods flow much better when they\n     * are not concerned with the lengths of strings, so a trick is employed to\n     * allow the get and put methods to view every string as an \"infinite\"\n     * sequence of bits. Logically, every string gets a '\\uffff' character,\n     * followed by an \"infinite\" sequence of '\\u0000' characters, appended to\n     * the end.\n     *\n     * Note that the '\\uffff' character serves to mark the end of the string,\n     * and it is necessary. Simply padding with '\\u0000' is insufficient to\n     * make all unique Unicode strings \"look\" unique to the get and put methods\n     * (because these methods do not regard string lengths).\n     */\n    private static boolean safeBitTest(String key, int b) {\n        if (b < key.length() * 16)      return bitTest(key, b) != 0;\n        if (b > key.length() * 16 + 15) return false;   // padding\n        /* 16 bits of 0xffff */         return true;    // end marker\n    }\n\n    private static int bitTest(String key, int b) {\n        return (key.charAt(b >>> 4) >>> (b & 0xf)) & 1;\n    }\n\n    /* Like the safeBitTest function, the safeCharAt function makes every\n     * string look like an \"infinite\" sequence of characters. Logically, every\n     * string gets a '\\uffff' character, followed by an \"infinite\" sequence of\n     * '\\u0000' characters, appended to the end.\n     */\n    private static int safeCharAt(String key, int i) {\n        if (i < key.length()) return key.charAt(i);\n        if (i > key.length()) return 0x0000;            // padding\n        else                  return 0xffff;            // end marker\n    }\n\n    /* For efficiency's sake, the firstDifferingBit function compares entire\n     * characters first, and then considers the individual bits (once it finds\n     * two characters that do not match). Also, the least significant bits of\n     * an individual character are examined first. There are many Unicode\n     * alphabets where most (if not all) of the \"action\" occurs in the least\n     * significant bits.\n     *\n     * Notice that the very first character comparison excludes the\n     * least-significant bit. The firstDifferingBit function must never return\n     * zero; otherwise, a node would become created as a child to the head\n     * (sentinel) node that matches the bit-index value (zero) stored in the\n     * head node. This would violate the invariant that bit-index values\n     * increase as you descend into the trie.\n     */\n    private static int firstDifferingBit(String k1, String k2) {\n        int i = 0;\n        int c1 = safeCharAt(k1, 0) & ~1;\n        int c2 = safeCharAt(k2, 0) & ~1;\n        if (c1 == c2) {\n            i = 1;\n            while (safeCharAt(k1, i) == safeCharAt(k2, i)) i++;\n            c1 = safeCharAt(k1, i);\n            c2 = safeCharAt(k2, i);\n        }\n        int b = 0;\n        while (((c1 >>> b) & 1) == ((c2 >>> b) & 1)) b++;\n        return i * 16 + b;\n    }\n\n    /**\n     * Unit tests the {@code PatriciaST} data type.\n     * This test fixture runs a series of tests on a randomly generated dataset.\n     * You may specify up to two integer parameters on the command line. The\n     * first parameter indicates the size of the dataset. The second parameter\n     * controls the number of passes (a new random dataset becomes generated at\n     * the start of each pass).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        PatriciaST<Integer> st = new PatriciaST<Integer>();\n        int limitItem = 1000000;\n        int limitPass = 1;\n        int countPass = 0;\n        boolean ok = true;\n\n        if (args.length > 0) limitItem = Integer.parseInt(args[0]);\n        if (args.length > 1) limitPass = Integer.parseInt(args[1]);\n\n        do {\n            String[] a = new String[limitItem];\n            int[]    v = new int[limitItem];\n\n            StdOut.printf(\"Creating dataset (%d items)...\\n\", limitItem);\n            for (int i = 0; i < limitItem; i++) {\n                a[i] = Integer.toString(i, 16);\n                v[i] = i;\n            }\n\n            StdOut.printf(\"Shuffling...\\n\");\n            StdRandom.shuffle(v);\n\n            StdOut.printf(\"Adding (%d items)...\\n\", limitItem);\n            for (int i = 0; i < limitItem; i++)\n                st.put(a[v[i]], v[i]);\n\n            int countKeys = 0;\n            StdOut.printf(\"Iterating...\\n\");\n            for (String key : st.keys()) countKeys++;\n            StdOut.printf(\"%d items iterated\\n\", countKeys);\n            if (countKeys != limitItem) ok = false;\n            if (countKeys != st.size()) ok = false;\n\n            StdOut.printf(\"Shuffling...\\n\");\n            StdRandom.shuffle(v);\n\n            int limitDelete = limitItem / 2;\n            StdOut.printf(\"Deleting (%d items)...\\n\", limitDelete);\n            for (int i = 0; i < limitDelete; i++)\n                st.delete(a[v[i]]);\n\n            countKeys = 0;\n            StdOut.printf(\"Iterating...\\n\");\n            for (String key : st.keys()) countKeys++;\n            StdOut.printf(\"%d items iterated\\n\", countKeys);\n            if (countKeys != limitItem - limitDelete) ok = false;\n            if (countKeys != st.size())               ok = false;\n\n            int countDelete = 0;\n            int countRemain = 0;\n            StdOut.printf(\"Checking...\\n\");\n            for (int i = 0; i < limitItem; i++) {\n                if (i < limitDelete) {\n                    if (!st.contains(a[v[i]])) countDelete++;\n                }\n                else {\n                    int val = st.get(a[v[i]]);\n                    if (val == v[i]) countRemain++;\n                }\n            }\n            StdOut.printf(\"%d items found and %d (deleted) items missing\\n\",\n                countRemain, countDelete);\n            if (countRemain + countDelete != limitItem) ok = false;\n            if (countRemain               != st.size()) ok = false;\n            if (st.isEmpty())                           ok = false;\n\n            StdOut.printf(\"Deleting the rest (%d items)...\\n\",\n                limitItem - countDelete);\n            for (int i = countDelete; i < limitItem; i++)\n                st.delete(a[v[i]]);\n            if (!st.isEmpty()) ok = false;\n\n            countPass++;\n            if (ok) StdOut.printf(\"PASS %d TESTS SUCCEEDED\\n\", countPass);\n            else    StdOut.printf(\"PASS %d TESTS FAILED\\n\",    countPass);\n        } while (ok && countPass < limitPass);\n\n        if (!ok) throw new java.lang.RuntimeException(\"TESTS FAILED\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Picture.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Picture.java\n *  Execution:    java Picture filename.jpg\n *  Dependencies: none\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.Color;\nimport java.awt.FileDialog;\nimport java.awt.Toolkit;\n\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.awt.event.KeyEvent;\nimport java.awt.event.WindowAdapter;\nimport java.awt.event.WindowEvent;\n\nimport java.awt.image.BufferedImage;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\n\nimport javax.imageio.ImageIO;\n\nimport javax.swing.ImageIcon;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.JPanel;\nimport javax.swing.KeyStroke;\n\n\n/**\n *  The {@code Picture} data type provides a basic capability for manipulating\n *  the individual pixels of an image.\n *  You can either create a blank image (of a given dimension) or read an\n *  image in a supported file format (typically JPEG, PNG, GIF, TIFF, and BMP).\n *  This class also includes methods for displaying the image in a window\n *  and saving it to a file.\n *\n *  <p>\n *  <b>Use in the curriculum.</b>\n *  The {@code Picture} class is intended for use in the\n *  curriculum once objects are introduced.\n *  The {@link StdPicture} class is intended for earlier use in\n *  the curriculum, before objects (but it can support only one\n *  picture at a time).\n *  See {@link GrayscalePicture} for a version that supports\n *  grayscale images.\n *\n *  <p>\n *  <b>Getting started.</b>\n *  To use this class, you must have {@code Picture} in your Java classpath.\n *  Here are three possible ways to do this:\n *  <ul>\n *  <li> If you ran our autoinstaller, use the commands\n *  {@code javac-introcs} and {@code java-introcs} (or {@code javac-algs4}\n *  and {@code java-algs4}) when compiling and executing. These commands\n *  add {@code stdlib.jar} (or {@code algs4.jar}) to the Java classpath, which\n *  provides access to {@code Picture}.\n *\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  (or <a href = \"https://algs4.cs.princeton.edu/code/algs4.jar\">algs4.jar</a>)\n *  and add it to the Java classpath.\n *\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdPicture.java\">StdPicture.java</a>\n *  and\n *  <a href = \"https://introcs.cs.princeton.edu/java/stdlib/Picture.java\">Picture.java</a>\n *  and put them in the working directory.\n *  </ul>\n *\n *  <p>\n *  As a test, cut-and-paste the following short program into your editor:\n *  <pre>\n *   public class TestPicture {\n *       public static void main(String[] args) {\n *           Picture picture = new Picture(\"https://introcs.cs.princeton.edu/java/stdlib/mandrill.jpg\");\n *           picture.show();\n *       }\n *   }\n *  </pre>\n *  <p>\n *  If you compile and execute the program, you should see a picture of a mandrill\n *  (a colorful monkey native to west-central Africa) in a window.\n *\n *  <p>\n *  <b>Anatomy of an image.</b>\n *  An image is a <em>width</em>-by-<em>height</em> grid of pixels, with pixel (0, 0)\n *  in the upper-left corner.\n *  Each pixel has a color that is represented using the <em>RGB color model</em>,\n *  which specifies the levels of <em>red</em> (R), <em>green</em> (G), and <em>blue</em> (B)\n *  on an integer scale from 0 to 255.\n *\n *  <blockquote>\n *  <img src = \"https://introcs.cs.princeton.edu/java/stdlib/AnatomyImage.png\" width = 200 alt = \"anatomy of an image\">\n *  </blockquote>\n *\n *  <p>\n *  <b>Creating pictures.</b>\n *  You can use the following constructors to create new {@code Picture} objects:\n *  <ul>\n *  <li> {@link #Picture(String filename)}\n *  <li> {@link #Picture(int width, int height)}\n *  </ul>\n *  <p>\n *  The first constructor read an image in a supported file format\n *  (typically JPEG, PNG, GIF, TIFF, and BMP)\n *  and initializes the picture to that image.\n *  The second constructor creates a <em>width</em>-by-<em>height</em> picture,\n *  with each pixel black.\n *\n *  <p>\n *  <b>Getting and setting the colors of the individual pixels.</b>\n *  You can use the following methods to get and set the color of a\n *  specified pixel:\n *  <ul>\n *  <li> {@link #get(int col, int row)}\n *  <li> {@link #set(int col, int row, Color color)}\n *  </ul>\n *  <p>\n *  The first method returns the color of pixel (<em>col</em>, <em>row</em>)\n *  as a {@code Color} object.\n *  The second method sets the color of pixel (<em>col</em>, <em>row</em>) to\n *  the specified color.\n *\n *  <p><b>Iterating over the pixels.</b>\n *  A common operation in image processing is to iterate over and process\n *  all of the pixels in an image.\n *  Here is a prototypical example that creates a grayscale version of a color image,\n *  using the NTSC formula\n *  <em>Y</em> = 0.299<em>r</em> + 0.587<em>g</em> + 0.114<em>b</em>.\n *  Note that if the red, green, and blue components of an RGB color\n *  are all equal, the color is a shade of gray.\n *  <pre>\n *  Picture picture   = new Picture(\"https://introcs.cs.princeton.edu/java/stdlib/mandrill.jpg\");\n *  Picture grayscale = new Picture(picture.width(), picture.height());\n *  for (int col = 0; col &lt; picture.width(); col++) {\n *      for (int row = 0; row &lt; picture.height(); row++) {\n *          Color color = picture.get(col, row);\n *          int r = color.getRed();\n *          int g = color.getGreen();\n *          int b = color.getBlue();\n *          int y = (int) (Math.round(0.299*r + 0.587*g + 0.114*b));\n *          Color gray = new Color(y, y, y);\n *          grayscale.set(col, row, gray);\n *      }\n *  }\n *  picture.show();\n *  grayscale.show();\n *  </pre>\n *\n *  <p><b>Transparency.</b>\n *  Both the {@link Color} and {@code Picture} classes support\n *  transparency, using the <em>alpha channel</em>.\n *  The alpha value defines the transparency of a color, with 0 corresponding to\n *  completely transparent and 255 to completely opaque. If transparency is not\n *  explicitly used, the alpha values is 255.\n *\n *  <p><b>32-bit color.</b>\n *  Sometimes it is more convenient (or efficient) to manipulate the\n *  color of a pixel as a single 32-bit integers instead of four 8-bit components.\n *  The following methods support this:\n *  <ul>\n *  <li> {@link #getARGB(int col, int row)}\n *  <li> {@link #setARGB(int col, int row, int rgb)}\n *  </ul>\n *  <p>\n *  The alpha (A), red (R), green (G), and blue (B) components\n *  are encoded as a single 32-bit integer.\n *  Given a 32-bit {@code int} encoding the color, the following code extracts\n *  the ARGB components:\n * <blockquote><pre>\n *  int a = (rgb &gt;&gt; 24) &amp; 0xFF;\n *  int r = (rgb &gt;&gt; 16) &amp; 0xFF;\n *  int g = (rgb &gt;&gt;  8) &amp; 0xFF;\n *  int b = (rgb &gt;&gt;  0) &amp; 0xFF;\n *  </pre></blockquote>\n *  Given the ARGB components (8-bits each) of a color,\n *  the following statement packs it into a 32-bit {@code int}:\n *  <blockquote><pre>\n *  int argb = (a &lt;&lt; 24) | (r &lt;&lt; 16) | (g &lt;&lt; 8) | (b &lt;&lt; 0);\n *  </pre></blockquote>\n *\n *  <p><b>Coordinates.</b>\n *  Pixel (<em>col</em>, <em>row</em>) is column <em>col</em> and row <em>row</em>.\n *  By default, the origin (0, 0) is the pixel in the upper-left corner.\n *  These are common conventions in image processing and consistent with Java's\n *  {@link java.awt.image.BufferedImage} data type. The following\n *  two methods allow you to change this convention:\n *  <ul>\n *  <li> {@link #setOriginLowerLeft()}\n *  <li> {@link #setOriginUpperLeft()}\n *  </ul>\n *\n *  <p><b>Saving files.</b>\n *  The {@code Picture} class supports writing images to a supported\n *  file format (typically JPEG, PNG, GIF, TIFF, and BMP).\n *  You can save the picture to a file using these two methods:\n *  <ul>\n *  <li> {@link #save(String filename)}\n *  <li> {@link #save(File file)}\n *  </ul>\n *\n *  <p>Alternatively, you can save the picture interactively\n *  by using the menu option <em>File → Save</em> from the picture window.\n *\n *  <p><b>File formats.</b>\n *  The {@code Picture} class supports reading and writing images to any of the\n *  file formats supported by {@link javax.imageio} (typically JPEG, PNG,\n *  GIF, TIFF, and BMP).\n *  The file extensions corresponding to JPEG, PNG, GIF, TIFF, and BMP,\n *  are {@code .jpg}, {@code .png}, {@code .gif}, {@code .tif},\n *  and {@code .bmp}, respectively.\n *  The file formats JPEG and BMP do not support transparency.\n *\n *  <p><b>Memory usage.</b>\n *  A <em>W</em>-by-<em>H</em> picture uses ~ 4 <em>W H</em> bytes of memory,\n *  since the color of each pixel is encoded as a 32-bit <code>int</code>.\n *\n *  <p><b>Additional documentation.</b>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class Picture implements ActionListener {\n    private BufferedImage image;               // the rasterized image\n    private JFrame jframe;                     // on-screen view\n    private String title;                      // window title (typically the name of the file)\n    private boolean isOriginUpperLeft = true;  // location of origin\n    private boolean isVisible = false;         // is the frame visible?\n    private boolean isDisposed = false;        // has the window been disposed?\n    private final int width, height;           // width and height\n\n   /**\n     * Creates a {@code width}-by-{@code height} picture, with {@code width} columns\n     * and {@code height} rows, where each pixel is black.\n     *\n     * @param width the width of the picture\n     * @param height the height of the picture\n     * @throws IllegalArgumentException if {@code width} is negative or zero\n     * @throws IllegalArgumentException if {@code height} is negative or zero\n     */\n    public Picture(int width, int height) {\n        if (width  <= 0) throw new IllegalArgumentException(\"width must be positive\");\n        if (height <= 0) throw new IllegalArgumentException(\"height must be positive\");\n        this.width  = width;\n        this.height = height;\n        this.title = width + \"-by-\" + height;\n        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\n    }\n\n   /**\n     * Creates a new picture that is a deep copy of the argument picture.\n     *\n     * @param  picture the picture to copy\n     * @throws IllegalArgumentException if {@code picture} is {@code null}\n     */\n    public Picture(Picture picture) {\n        if (picture == null) throw new IllegalArgumentException(\"constructor argument is null\");\n\n        width  = picture.width();\n        height = picture.height();\n        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\n        title = picture.title;\n        isOriginUpperLeft = picture.isOriginUpperLeft;\n        for (int col = 0; col < width(); col++)\n            for (int row = 0; row < height(); row++)\n                image.setRGB(col, row, picture.image.getRGB(col, row));\n    }\n\n   /**\n     * Creates a picture by reading a JPEG, PNG, GIF , BMP, or TIFF image\n     * from a file or URL.\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     *\n     * @param  filename the name of the file or URL\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if cannot read image from file or URL\n     */\n    public Picture(String filename) {\n        if (filename == null) throw new IllegalArgumentException(\"constructor argument is null\");\n        if (filename.length() == 0) throw new IllegalArgumentException(\"constructor argument is the empty string\");\n\n        title = filename;\n        try {\n            // try to read from file in working directory\n            File file = new File(filename);\n            if (file.isFile()) {\n                title = file.getName();\n                image = ImageIO.read(file);\n            }\n\n            else {\n\n                // resource relative to .class file\n                URL url = getClass().getResource(filename);\n\n                // resource relative to classloader root\n                if (url == null) {\n                    url = getClass().getClassLoader().getResource(filename);\n                }\n\n                // or URL from web or jar\n                if (url == null) {\n                    URI uri = new URI(filename);\n                    if (uri.isAbsolute()) url = uri.toURL();\n                    else throw new IllegalArgumentException(\"could not read image: '\" + filename + \"'\");\n                }\n\n                image = ImageIO.read(url);\n            }\n\n            if (image == null) {\n                throw new IllegalArgumentException(\"could not read image: '\" + filename + \"'\");\n            }\n\n            width  = image.getWidth(null);\n            height = image.getHeight(null);\n\n            // convert to ARGB if necessary\n            if (image.getType() != BufferedImage.TYPE_INT_ARGB) {\n                BufferedImage imageARGB = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\n                // the next line causes JVM app icon to previous display in Dock on OS X\n                imageARGB.createGraphics().drawImage(image, 0, 0, null);\n                image = imageARGB;\n            }\n        }\n        catch (IOException | URISyntaxException e) {\n            throw new IllegalArgumentException(\"could not open image: \" + filename, e);\n        }\n    }\n\n   /**\n     * Creates a picture by reading the image from a JPEG, PNG, GIF, BMP, or TIFF file.\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     *\n     * @param file the file\n     * @throws IllegalArgumentException if cannot read image\n     * @throws IllegalArgumentException if {@code file} is {@code null}\n     */\n    public Picture(File file) {\n        if (file == null) throw new IllegalArgumentException(\"constructor argument is null\");\n\n        try {\n            image = ImageIO.read(file);\n\n            width  = image.getWidth(null);\n            height = image.getHeight(null);\n            title = file.getName();\n\n            // convert to ARGB\n            if (image.getType() != BufferedImage.TYPE_INT_RGB) {\n                BufferedImage imageARGB = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\n                imageARGB.createGraphics().drawImage(image, 0, 0, null);\n                image = imageARGB;\n            }\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"could not open file: \" + file, ioe);\n        }\n    }\n\n    // create the GUI for viewing the image if needed\n    @SuppressWarnings(\"deprecation\")\n    private JFrame createGUI() {\n        JFrame frame = new JFrame();\n        JMenuBar menuBar = new JMenuBar();\n        JMenu menu = new JMenu(\"File\");\n        menuBar.add(menu);\n        JMenuItem menuItem1 = new JMenuItem(\" Save...   \");\n        menuItem1.addActionListener(this);\n  \t// Java 11:  use getMenuShortcutKeyMaskEx()\n        // Java 8:   use getMenuShortcutKeyMask()\n        menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,\n                                 Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));\n        menu.add(menuItem1);\n        frame.setJMenuBar(menuBar);\n\n        frame.setContentPane(getJLabel());\n        // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);\n        frame.setTitle(title);\n        frame.setResizable(false);\n        frame.pack();\n\n        frame.addWindowListener(new WindowAdapter() {\n            public void windowClosing(WindowEvent event){\n                isVisible = false;\n                isDisposed = true;\n                super.windowClosing(event);\n            }\n        });\n        return frame;\n    }\n\n   /**\n     * Returns a {@link JLabel} containing this picture, for embedding in a {@link JPanel},\n     * {@link JFrame} or other GUI widget.\n     *\n     * @return the {@code JLabel}\n     */\n    public JLabel getJLabel() {\n        if (image == null) return null;         // no image available\n        ImageIcon icon = new ImageIcon(image);\n        return new JLabel(icon);\n    }\n\n   /**\n     * Sets the origin (0, 0) to be the upper left pixel. This is the default.\n     */\n    public void setOriginUpperLeft() {\n        isOriginUpperLeft = true;\n    }\n\n   /**\n     * Sets the origin (0, 0) to be the lower left pixel.\n     */\n    public void setOriginLowerLeft() {\n        isOriginUpperLeft = false;\n    }\n\n   /**\n     * Displays the picture in a window on the screen.\n     */\n\n    // getMenuShortcutKeyMask() deprecated in Java 10 but its replacement\n    // getMenuShortcutKeyMaskEx() is not available in Java 8\n    @SuppressWarnings(\"deprecation\")\n   /**\n     * Displays the picture in a window on the screen.\n     */\n    public void show() {\n        if (jframe == null && !isDisposed) {\n            jframe = createGUI();\n            isVisible = true;\n            jframe.setVisible(true);\n            jframe.repaint();\n        }\n\n        if (jframe != null && !isDisposed) {\n            isVisible = true;\n            jframe.setVisible(true);\n            jframe.repaint();\n        }\n    }\n\n   /**\n     * Hides the window containing the picture.\n     */\n    public void hide() {\n        if (jframe != null) {\n            isVisible = false;\n            jframe.setVisible(false);\n        }\n    }\n\n   /**\n     * Is the window containing the picture visible?\n     * @return {@code true} if the picture is visible, and {@code false} otherwise\n     */\n    public boolean isVisible() {\n        return isVisible;\n    }\n\n   /**\n     * Returns the height of the picture.\n     *\n     * @return the height of the picture (in pixels)\n     */\n    public int height() {\n        return height;\n    }\n\n   /**\n     * Returns the width of the picture.\n     *\n     * @return the width of the picture (in pixels)\n     */\n    public int width() {\n        return width;\n    }\n\n    private void validateRowIndex(int row) {\n        if (row < 0 || row >= height())\n            throw new IndexOutOfBoundsException(\"row index must be between 0 and \" + (height() - 1) + \": \" + row);\n    }\n\n    private void validateColumnIndex(int col) {\n        if (col < 0 || col >= width())\n            throw new IndexOutOfBoundsException(\"column index must be between 0 and \" + (width() - 1) + \": \" + col);\n    }\n\n   /**\n     * Returns the color of pixel ({@code col}, {@code row}) as a {@link java.awt.Color} object.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the color of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public Color get(int col, int row) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        int argb = getARGB(col, row);\n        return new Color(argb, true);\n    }\n\n   /**\n     * Returns the ARGB color of pixel ({@code col}, {@code row}) as a 32-bit integer.\n     * Using this method can be more efficient than {@link #get(int, int)} because\n     * it does not create a {@code Color} object.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the 32-bit integer representation of the ARGB color of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public int getARGB(int col, int row) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        if (isOriginUpperLeft) return image.getRGB(col, row);\n        else                   return image.getRGB(col, height - row - 1);\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given color.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param color the color\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     * @throws IllegalArgumentException if {@code color} is {@code null}\n     */\n    public void set(int col, int row, Color color) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        if (color == null) throw new IllegalArgumentException(\"color argument is null\");\n        int argb = color.getRGB();\n        setARGB(col, row, argb);\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given ARGB color.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param argb the 32-bit integer representation of the color\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public void setARGB(int col, int row, int argb) {\n        validateColumnIndex(col);\n        validateRowIndex(row);\n        if (isOriginUpperLeft) image.setRGB(col, row, argb);\n        else                   image.setRGB(col, height - row - 1, argb);\n    }\n\n   /**\n     * Returns {@code true} if this picture is equal to the argument picture,\n     * and {@code false} otherwise.\n     *\n     * @param other the other picture\n     * @return {@code true} if this picture is the same dimension as {@code other}\n     *         and if all pixels have the same color; {@code false} otherwise\n     */\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Picture that = (Picture) other;\n        if (this.width()  != that.width())  return false;\n        if (this.height() != that.height()) return false;\n        for (int col = 0; col < width(); col++)\n            for (int row = 0; row < height(); row++)\n                if (this.getARGB(col, row) != that.getARGB(col, row)) return false;\n        return true;\n    }\n\n   /**\n     * Returns a string representation of this picture.\n     * The result is a <code>width</code>-by-<code>height</code> matrix of pixels,\n     * where the color of a pixel is represented using 6 hex digits to encode\n     * the red, green, and blue components.\n     *\n     * @return a string representation of this picture\n     */\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(width +\"-by-\" + height + \" picture (RGB values given in hex)\\n\");\n        for (int row = 0; row < height; row++) {\n            for (int col = 0; col < width; col++) {\n                int rgb;\n                if (isOriginUpperLeft) rgb = image.getRGB(col, row);\n                else                   rgb = image.getRGB(col, height - row - 1);\n                sb.append(String.format(\"#%06X \", rgb & 0xFFFFFF));\n            }\n            sb.append(\"\\n\");\n        }\n        return sb.toString().trim();\n    }\n\n    /**\n     * This operation is not supported because pictures are mutable.\n     *\n     * @return does not return a value\n     * @throws UnsupportedOperationException if called\n     */\n    public int hashCode() {\n        throw new UnsupportedOperationException(\"hashCode() is not supported because pictures are mutable\");\n    }\n\n    /**\n     * Sets the title of this picture.\n     * @param title the title\n     * @throws IllegalArgumentException if {@code title} is {@code null}\n     */\n    public void setTitle(String title) {\n        if (title == null) throw new IllegalArgumentException(\"title is null\");\n        this.title = title;\n    }\n\n    // does this picture use transparency (i.e., alpha < 255 for some pixel)?\n    private boolean hasAlpha() {\n        for (int col = 0; col < width; col++) {\n            for (int row = 0; row < height; row++) {\n                int argb = image.getRGB(col, row);\n                int alpha =  (argb >> 24) & 0xFF;\n                if (alpha != 255) return true;\n            }\n        }\n        return false;\n    }\n\n   /**\n     * Saves the picture to a file in a supported file format\n     * (typically JPEG, PNG, GIF, TIFF, and BMP).\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     * If the file format does not support transparency (such as JPEG\n     * or BMP), it will be converted to be opaque (with purely\n     * transparent pixels converted to black).\n     *\n     * @param filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if {@code filename} has invalid filetype extension\n     * @throws IllegalArgumentException if cannot write the file {@code filename}\n     */\n    public void save(String filename) {\n        if (filename == null) throw new IllegalArgumentException(\"argument to save() is null\");\n        if (filename.length() == 0) throw new IllegalArgumentException(\"argument to save() is the empty string\");\n        File file = new File(filename);\n        save(file);\n    }\n\n   /**\n     * Saves the picture to a file in a supported file format\n     * (typically JPEG, PNG, GIF, TIFF, and BMP).\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     * If the file format does not support transparency (such as JPEG\n     * or BMP), it will be converted to be opaque (with purely\n     * transparent pixels converted to black).\n     *\n     * @param  file the file\n     * @throws IllegalArgumentException if {@code file} is {@code null}\n     */\n    public void save(File file) {\n        if (file == null) throw new IllegalArgumentException(\"argument to save() is null\");\n        title = file.getName();\n\n        String suffix = title.substring(title.lastIndexOf('.') + 1);\n        if (!title.contains(\".\") || suffix.length() == 0) {\n            throw new IllegalArgumentException(\"The filename '\" + title + \"' has no filetype extension, such as .jpg or .png\");\n        }\n\n        try {\n            // for formats that support transparency (e.g., PNG and GIF)\n            if (ImageIO.write(image, suffix, file)) return;\n\n            // for formats that don't support transparency (e.g., JPG and BMP)\n            // create BufferedImage in RGB format and use white background\n            BufferedImage imageRGB = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\n            imageRGB.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);\n            if (ImageIO.write(imageRGB, suffix, file)) return;\n\n            // failed to save the file; probably wrong format\n            throw new IllegalArgumentException(\"The filetype '\" + suffix + \"' is not supported\");\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not write file '\" + title + \"'\", e);\n        }\n    }\n\n   /**\n     * Opens a save dialog box when the user selects \"Save As\" from the menu.\n     */\n    @Override\n    public void actionPerformed(ActionEvent event) {\n        FileDialog chooser = new FileDialog(jframe,\n                             \"The filetype extension must be either .jpg or .png\", FileDialog.SAVE);\n        chooser.setVisible(true);\n        String selectedDirectory = chooser.getDirectory();\n        String selectedFilename = chooser.getFile();\n        if (selectedDirectory != null && selectedFilename != null) {\n            try {\n                save(selectedDirectory + selectedFilename);\n            }\n            catch (IllegalArgumentException e) {\n                System.err.println(e.getMessage());\n            }\n        }\n    }\n\n   /**\n     * Unit tests this {@code Picture} data type.\n     * Reads a picture specified by the command-line argument,\n     * and shows it in a window on the screen.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Picture picture = new Picture(args[0]);\n        System.out.printf(\"%d-by-%d\\n\", picture.width(), picture.height());\n        picture.show();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/PictureDump.java",
    "content": "/******************************************************************************\n *  Compilation:  javac PictureDump.java\n *  Execution:    java PictureDump width height < file\n *  Dependencies: BinaryStdIn.java Picture.java\n *  Data file:    http://introcs.cs.princeton.edu/stdlib/abra.txt\n *\n *  Reads in a binary file and writes out the bits as w-by-h picture,\n *  with the 1 bits in black and the 0 bits in white.\n *\n *  % more abra.txt\n *  ABRACADABRA!\n *\n *  % java PictureDump 16 6 < abra.txt\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.Color;\n\n\n/**\n *  The {@code PictureDump} class provides a client for displaying the contents\n *  of a binary file as a black-and-white picture.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  <p>\n *  See also {@link BinaryDump} and {@link HexDump}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class PictureDump {\n\n    // Do not instantiate.\n    private PictureDump() { }\n\n    /**\n     * Reads in a sequence of bytes from standard input and draws\n     * them to standard drawing output as a width-by-height picture,\n     * using black for 1 and white for 0 (and red for any leftover\n     * pixels).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int width = Integer.parseInt(args[0]);\n        int height = Integer.parseInt(args[1]);\n        Picture picture = new Picture(width, height);\n        for (int row = 0; row < height; row++) {\n            for (int col = 0; col < width; col++) {\n                if (!BinaryStdIn.isEmpty()) {\n                    boolean bit = BinaryStdIn.readBoolean();\n                    if (bit) picture.set(col, row, Color.BLACK);\n                    else     picture.set(col, row, Color.WHITE);\n                }\n                else {\n                    picture.set(col, row, Color.RED);\n                }\n            }\n        }\n        picture.show();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Point2D.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Point2D.java\n *  Execution:    java Point2D x0 y0 n\n *  Dependencies: StdDraw.java StdRandom.java\n *\n *  Immutable point data type for points in the plane.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\nimport java.util.Comparator;\n\n\n/**\n *  The {@code Point} class is an immutable data type to encapsulate a\n *  two-dimensional point with real-value coordinates.\n *  <p>\n *  Note: in order to deal with the difference behavior of double and\n *  Double with respect to -0.0 and +0.0, the Point2D constructor converts\n *  any coordinates that are -0.0 to +0.0.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class Point2D implements Comparable<Point2D> {\n\n    /**\n     * Compares two points by x-coordinate.\n     */\n    public static final Comparator<Point2D> X_ORDER = new XOrder();\n\n    /**\n     * Compares two points by y-coordinate.\n     */\n    public static final Comparator<Point2D> Y_ORDER = new YOrder();\n\n    /**\n     * Compares two points by polar radius.\n     */\n    public static final Comparator<Point2D> R_ORDER = new ROrder();\n\n    private final double x;    // x coordinate\n    private final double y;    // y coordinate\n\n    /**\n     * Initializes a new point (x, y).\n     * @param x the x-coordinate\n     * @param y the y-coordinate\n     * @throws IllegalArgumentException if either {@code x} or {@code y}\n     *    is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY} or\n     *    {@code Double.NEGATIVE_INFINITY}\n     */\n    public Point2D(double x, double y) {\n        if (Double.isInfinite(x) || Double.isInfinite(y))\n            throw new IllegalArgumentException(\"Coordinates must be finite\");\n        if (Double.isNaN(x) || Double.isNaN(y))\n            throw new IllegalArgumentException(\"Coordinates cannot be NaN\");\n        if (x == 0.0) this.x = 0.0;  // convert -0.0 to +0.0\n        else          this.x = x;\n\n        if (y == 0.0) this.y = 0.0;  // convert -0.0 to +0.0\n        else          this.y = y;\n    }\n\n    /**\n     * Returns the x-coordinate.\n     * @return the x-coordinate\n     */\n    public double x() {\n        return x;\n    }\n\n    /**\n     * Returns the y-coordinate.\n     * @return the y-coordinate\n     */\n    public double y() {\n        return y;\n    }\n\n    /**\n     * Returns the polar radius of this point.\n     * @return the polar radius of this point in polar coordinates: sqrt(x*x + y*y)\n     */\n    public double r() {\n        return Math.sqrt(x*x + y*y);\n    }\n\n    /**\n     * Returns the angle of this point in polar coordinates.\n     * @return the angle (in radians) of this point in polar coordinates (between –&pi; and &pi;)\n     */\n    public double theta() {\n        return Math.atan2(y, x);\n    }\n\n    /**\n     * Returns the angle between this point and that point.\n     * @return the angle in radians (between –&pi; and &pi;) between this point and that point (0 if equal)\n     */\n    private double angleTo(Point2D that) {\n        double dx = that.x - this.x;\n        double dy = that.y - this.y;\n        return Math.atan2(dy, dx);\n    }\n\n    /**\n     * Returns true if a→b→c is a counterclockwise turn.\n     * @param a first point\n     * @param b second point\n     * @param c third point\n     * @return { -1, 0, +1 } if a→b→c is a { clockwise, collinear; counterclockwise } turn.\n     */\n    public static int ccw(Point2D a, Point2D b, Point2D c) {\n        double area2 = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);\n        if      (area2 < 0) return -1;\n        else if (area2 > 0) return +1;\n        else                return  0;\n    }\n\n    /**\n     * Returns twice the signed area of the triangle a-b-c.\n     * @param a first point\n     * @param b second point\n     * @param c third point\n     * @return twice the signed area of the triangle a-b-c\n     */\n    public static double area2(Point2D a, Point2D b, Point2D c) {\n        return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);\n    }\n\n    /**\n     * Returns the Euclidean distance between this point and that point.\n     * @param that the other point\n     * @return the Euclidean distance between this point and that point\n     */\n    public double distanceTo(Point2D that) {\n        double dx = this.x - that.x;\n        double dy = this.y - that.y;\n        return Math.sqrt(dx*dx + dy*dy);\n    }\n\n    /**\n     * Returns the square of the Euclidean distance between this point and that point.\n     * @param that the other point\n     * @return the square of the Euclidean distance between this point and that point\n     */\n    public double distanceSquaredTo(Point2D that) {\n        double dx = this.x - that.x;\n        double dy = this.y - that.y;\n        return dx*dx + dy*dy;\n    }\n\n    /**\n     * Compares two points by y-coordinate, breaking ties by x-coordinate.\n     * Formally, the invoking point (x0, y0) is less than the argument point (x1, y1)\n     * if and only if either {@code y0 < y1} or if {@code y0 == y1} and {@code x0 < x1}.\n     *\n     * @param  that the other point\n     * @return the value {@code 0} if this string is equal to the argument\n     *         string (precisely when {@code equals()} returns {@code true});\n     *         a negative integer if this point is less than the argument\n     *         point; and a positive integer if this point is greater than the\n     *         argument point\n     */\n    public int compareTo(Point2D that) {\n        if (this.y < that.y) return -1;\n        if (this.y > that.y) return +1;\n        if (this.x < that.x) return -1;\n        if (this.x > that.x) return +1;\n        return 0;\n    }\n\n    /**\n     * Compares two points by polar angle (between 0 and 2&pi;) with respect to this point.\n     *\n     * @return the comparator\n     */\n    public Comparator<Point2D> polarOrder() {\n        return new PolarOrder();\n    }\n\n    /**\n     * Compares two points by atan2() angle (between –&pi; and &pi;) with respect to this point.\n     *\n     * @return the comparator\n     */\n    public Comparator<Point2D> atan2Order() {\n        return new Atan2Order();\n    }\n\n    /**\n     * Compares two points by distance to this point.\n     *\n     * @return the comparator\n     */\n    public Comparator<Point2D> distanceToOrder() {\n        return new DistanceToOrder();\n    }\n\n    // compare points according to their x-coordinate\n    private static class XOrder implements Comparator<Point2D> {\n        public int compare(Point2D p, Point2D q) {\n            return Double.compare(p.x, q.x);\n        }\n    }\n\n    // compare points according to their y-coordinate\n    private static class YOrder implements Comparator<Point2D> {\n        public int compare(Point2D p, Point2D q) {\n            return Double.compare(p.y, q.y);\n        }\n    }\n\n    // compare points according to their polar radius\n    private static class ROrder implements Comparator<Point2D> {\n        public int compare(Point2D p, Point2D q) {\n            double delta = (p.x*p.x + p.y*p.y) - (q.x*q.x + q.y*q.y);\n            return Double.compare(delta, 0);\n        }\n    }\n\n    // compare other points relative to atan2 angle (between -pi/2 and pi/2) they make with this Point\n    private class Atan2Order implements Comparator<Point2D> {\n        public int compare(Point2D q1, Point2D q2) {\n            double angle1 = angleTo(q1);\n            double angle2 = angleTo(q2);\n            return Double.compare(angle1, angle2);\n        }\n    }\n\n    // compare other points relative to polar angle (between 0 and 2pi) they make with this Point\n    private class PolarOrder implements Comparator<Point2D> {\n        public int compare(Point2D q1, Point2D q2) {\n            double dx1 = q1.x - x;\n            double dy1 = q1.y - y;\n            double dx2 = q2.x - x;\n            double dy2 = q2.y - y;\n\n            if      (dy1 >= 0 && dy2 < 0) return -1;    // q1 above; q2 below\n            else if (dy2 >= 0 && dy1 < 0) return +1;    // q1 below; q2 above\n            else if (dy1 == 0 && dy2 == 0) {            // 3-collinear and horizontal\n                if      (dx1 >= 0 && dx2 < 0) return -1;\n                else if (dx2 >= 0 && dx1 < 0) return +1;\n                else                          return  0;\n            }\n            else return -ccw(Point2D.this, q1, q2);     // both above or below\n\n            // Note: ccw() recomputes dx1, dy1, dx2, and dy2\n        }\n    }\n\n    // compare points according to their distance to this point\n    private class DistanceToOrder implements Comparator<Point2D> {\n        public int compare(Point2D p, Point2D q) {\n            double dist1 = distanceSquaredTo(p);\n            double dist2 = distanceSquaredTo(q);\n            return Double.compare(dist1, dist2);\n        }\n    }\n\n\n    /**\n     * Compares this point to the specified point.\n     *\n     * @param  other the other point\n     * @return {@code true} if this point equals {@code other};\n     *         {@code false} otherwise\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Point2D that = (Point2D) other;\n        return this.x == that.x && this.y == that.y;\n    }\n\n    /**\n     * Return a string representation of this point.\n     * @return a string representation of this point in the format (x, y)\n     */\n    @Override\n    public String toString() {\n        return \"(\" + x + \", \" + y + \")\";\n    }\n\n    /**\n     * Returns an integer hash code for this point.\n     * @return an integer hash code for this point\n     */\n    @Override\n    public int hashCode() {\n        int hashX = ((Double) x).hashCode();\n        int hashY = ((Double) y).hashCode();\n        return 31*hashX + hashY;\n    }\n\n    /**\n     * Plot this point using standard draw.\n     */\n    public void draw() {\n        StdDraw.point(x, y);\n    }\n\n    /**\n     * Plot a line from this point to that point using standard draw.\n     * @param that the other point\n     */\n    public void drawTo(Point2D that) {\n        StdDraw.line(this.x, this.y, that.x, that.y);\n    }\n\n\n    /**\n     * Unit tests the point data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int x0 = Integer.parseInt(args[0]);\n        int y0 = Integer.parseInt(args[1]);\n        int n = Integer.parseInt(args[2]);\n\n        StdDraw.setCanvasSize(800, 800);\n        StdDraw.setXscale(0, 100);\n        StdDraw.setYscale(0, 100);\n        StdDraw.setPenRadius(0.005);\n        StdDraw.enableDoubleBuffering();\n\n        Point2D[] points = new Point2D[n];\n        for (int i = 0; i < n; i++) {\n            int x = StdRandom.uniformInt(100);\n            int y = StdRandom.uniformInt(100);\n            points[i] = new Point2D(x, y);\n            points[i].draw();\n        }\n\n        // draw p = (x0, x1) in red\n        Point2D p = new Point2D(x0, y0);\n        StdDraw.setPenColor(StdDraw.RED);\n        StdDraw.setPenRadius(0.02);\n        p.draw();\n\n\n        // draw line segments from p to each point, one at a time, in polar order\n        StdDraw.setPenRadius();\n        StdDraw.setPenColor(StdDraw.BLUE);\n        Arrays.sort(points, p.polarOrder());\n        for (int i = 0; i < n; i++) {\n            p.drawTo(points[i]);\n            StdDraw.show();\n            StdDraw.pause(100);\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Polynomial.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Polynomial.java\n *  Execution:    java Polynomial\n *\n *  Polynomials with integer coefficients.\n *\n *  % java Polynomial\n *  zero(x)     = 0\n *  p(x)        = 4x^3 + 3x^2 + 2x + 1\n *  q(x)        = 3x^2 + 5\n *  p(x) + q(x) = 4x^3 + 6x^2 + 2x + 6\n *  p(x) * q(x) = 12x^5 + 9x^4 + 26x^3 + 18x^2 + 10x + 5\n *  p(q(x))     = 108x^6 + 567x^4 + 996x^2 + 586\n *  p(x) - p(x) = 0\n *  0 - p(x)    = -4x^3 - 3x^2 - 2x - 1\n *  p(3)        = 142\n *  p'(x)       = 12x^2 + 6x + 2\n *  p''(x)      = 24x + 6\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Polynomial} class represents a polynomial with integer\n *  coefficients.\n *  Polynomials are immutable: their values cannot be changed after they\n *  are created.\n *  It includes methods for addition, subtraction, multiplication, composition,\n *  differentiation, and evaluation.\n *  <p>\n *  This computes correct results if all arithmetic performed is\n *  without overflow.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/99scientific\">Section 9.9</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Polynomial {\n    private int[] coef;   // coefficients p(x) = sum { coef[i] * x^i }\n    private int degree;   // degree of polynomial (-1 for the zero polynomial)\n\n    /**\n     * Initializes a new polynomial a x^b\n     * @param a the leading coefficient\n     * @param b the exponent\n     * @throws IllegalArgumentException if {@code b} is negative\n     */\n    public Polynomial(int a, int b) {\n        if (b < 0) {\n            throw new IllegalArgumentException(\"exponent cannot be negative: \" + b);\n        }\n        coef = new int[b+1];\n        coef[b] = a;\n        reduce();\n    }\n\n    // pre-compute the degree of the polynomial, in case of leading zero coefficients\n    // (that is, the length of the array need not relate to the degree of the polynomial)\n    private void reduce() {\n        degree = -1;\n        for (int i = coef.length - 1; i >= 0; i--) {\n            if (coef[i] != 0) {\n                degree = i;\n                return;\n            }\n        }\n    }\n\n    /**\n     * Returns the degree of this polynomial.\n     * @return the degree of this polynomial, -1 for the zero polynomial.\n     */\n    public int degree() {\n        return degree;\n    }\n\n    /**\n     * Returns the sum of this polynomial and the specified polynomial.\n     *\n     * @param  that the other polynomial\n     * @return the polynomial whose value is {@code (this(x) + that(x))}\n     */\n    public Polynomial plus(Polynomial that) {\n        Polynomial poly = new Polynomial(0, Math.max(this.degree, that.degree));\n        for (int i = 0; i <= this.degree; i++) poly.coef[i] += this.coef[i];\n        for (int i = 0; i <= that.degree; i++) poly.coef[i] += that.coef[i];\n        poly.reduce();\n        return poly;\n    }\n\n    /**\n     * Returns the result of subtracting the specified polynomial\n     * from this polynomial.\n     *\n     * @param  that the other polynomial\n     * @return the polynomial whose value is {@code (this(x) - that(x))}\n     */\n    public Polynomial minus(Polynomial that) {\n        Polynomial poly = new Polynomial(0, Math.max(this.degree, that.degree));\n        for (int i = 0; i <= this.degree; i++) poly.coef[i] += this.coef[i];\n        for (int i = 0; i <= that.degree; i++) poly.coef[i] -= that.coef[i];\n        poly.reduce();\n        return poly;\n    }\n\n    /**\n     * Returns the product of this polynomial and the specified polynomial.\n     * Takes time proportional to the product of the degrees.\n     * (Faster algorithms are known, e.g., via FFT.)\n     *\n     * @param  that the other polynomial\n     * @return the polynomial whose value is {@code (this(x) * that(x))}\n     */\n    public Polynomial times(Polynomial that) {\n        Polynomial poly = new Polynomial(0, this.degree + that.degree);\n        for (int i = 0; i <= this.degree; i++)\n            for (int j = 0; j <= that.degree; j++)\n                poly.coef[i+j] += (this.coef[i] * that.coef[j]);\n        poly.reduce();\n        return poly;\n    }\n\n    /**\n     * Returns the composition of this polynomial and the specified\n     * polynomial.\n     * Takes time proportional to the product of the degrees.\n     * (Faster algorithms are known, e.g., via FFT.)\n     *\n     * @param  that the other polynomial\n     * @return the polynomial whose value is {@code (this(that(x)))}\n     */\n    public Polynomial compose(Polynomial that) {\n        Polynomial poly = new Polynomial(0, 0);\n        for (int i = this.degree; i >= 0; i--) {\n            Polynomial term = new Polynomial(this.coef[i], 0);\n            poly = term.plus(that.times(poly));\n        }\n        return poly;\n    }\n\n\n    /**\n     * Compares this polynomial to the specified polynomial.\n     *\n     * @param  other the other polynomial\n     * @return {@code true} if this polynomial equals {@code other};\n     *         {@code false} otherwise\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Polynomial that = (Polynomial) other;\n        if (this.degree != that.degree) return false;\n        for (int i = this.degree; i >= 0; i--)\n            if (this.coef[i] != that.coef[i]) return false;\n        return true;\n    }\n\n    /**\n     * Returns the result of differentiating this polynomial.\n     *\n     * @return the polynomial whose value is {@code this'(x)}\n     */\n    public Polynomial differentiate() {\n        if (degree == 0) return new Polynomial(0, 0);\n        Polynomial poly = new Polynomial(0, degree - 1);\n        poly.degree = degree - 1;\n        for (int i = 0; i < degree; i++)\n            poly.coef[i] = (i + 1) * coef[i + 1];\n        return poly;\n    }\n\n    /**\n     * Returns the result of evaluating this polynomial at the point x.\n     *\n     * @param  x the point at which to evaluate the polynomial\n     * @return the integer whose value is {@code (this(x))}\n     */\n    public int evaluate(int x) {\n        int p = 0;\n        for (int i = degree; i >= 0; i--)\n            p = coef[i] + (x * p);\n        return p;\n    }\n\n    /**\n     * Compares two polynomials by degree, breaking ties by coefficient of leading term.\n     *\n     * @param  that the other point\n     * @return the value {@code 0} if this polynomial is equal to the argument\n     *         polynomial (precisely when {@code equals()} returns {@code true});\n     *         a negative integer if this polynomial is less than the argument\n     *         polynomial; and a positive integer if this polynomial is greater than the\n     *         argument point\n     */\n    public int compareTo(Polynomial that) {\n        if (this.degree < that.degree) return -1;\n        if (this.degree > that.degree) return +1;\n        for (int i = this.degree; i >= 0; i--) {\n            if (this.coef[i] < that.coef[i]) return -1;\n            if (this.coef[i] > that.coef[i]) return +1;\n        }\n        return 0;\n    }\n\n    /**\n     * Return a string representation of this polynomial.\n     * @return a string representation of this polynomial in the format\n     *         4x^5 - 3x^2 + 11x + 5\n     */\n    @Override\n    public String toString() {\n        if      (degree == -1) return \"0\";\n        else if (degree ==  0) return \"\" + coef[0];\n        else if (degree ==  1) return coef[1] + \"x + \" + coef[0];\n        String s = coef[degree] + \"x^\" + degree;\n        for (int i = degree - 1; i >= 0; i--) {\n            if      (coef[i] == 0) continue;\n            else if (coef[i]  > 0) s = s + \" + \" + (coef[i]);\n            else if (coef[i]  < 0) s = s + \" - \" + (-coef[i]);\n            if      (i == 1) s = s + \"x\";\n            else if (i >  1) s = s + \"x^\" + i;\n        }\n        return s;\n    }\n\n    /**\n     * Unit tests the polynomial data type.\n     *\n     * @param args the command-line arguments (none)\n     */\n    public static void main(String[] args) {\n        Polynomial zero = new Polynomial(0, 0);\n\n        Polynomial p1   = new Polynomial(4, 3);\n        Polynomial p2   = new Polynomial(3, 2);\n        Polynomial p3   = new Polynomial(1, 0);\n        Polynomial p4   = new Polynomial(2, 1);\n        Polynomial p    = p1.plus(p2).plus(p3).plus(p4);   // 4x^3 + 3x^2 + 1\n\n        Polynomial q1   = new Polynomial(3, 2);\n        Polynomial q2   = new Polynomial(5, 0);\n        Polynomial q    = q1.plus(q2);                     // 3x^2 + 5\n\n\n        Polynomial r    = p.plus(q);\n        Polynomial s    = p.times(q);\n        Polynomial t    = p.compose(q);\n        Polynomial u    = p.minus(p);\n\n        StdOut.println(\"zero(x)     = \" + zero);\n        StdOut.println(\"p(x)        = \" + p);\n        StdOut.println(\"q(x)        = \" + q);\n        StdOut.println(\"p(x) + q(x) = \" + r);\n        StdOut.println(\"p(x) * q(x) = \" + s);\n        StdOut.println(\"p(q(x))     = \" + t);\n        StdOut.println(\"p(x) - p(x) = \" + u);\n        StdOut.println(\"0 - p(x)    = \" + zero.minus(p));\n        StdOut.println(\"p(3)        = \" + p.evaluate(3));\n        StdOut.println(\"p'(x)       = \" + p.differentiate());\n        StdOut.println(\"p''(x)      = \" + p.differentiate().differentiate());\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/PrimMST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac PrimMST.java\n *  Execution:    java PrimMST filename.txt\n *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java\n *                IndexMinPQ.java UF.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt\n *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt\n *\n *  Compute a minimum spanning forest using Prim's algorithm.\n *\n *  %  java PrimMST tinyEWG.txt\n *  1-7 0.19000\n *  0-2 0.26000\n *  2-3 0.17000\n *  4-5 0.35000\n *  5-7 0.28000\n *  6-2 0.40000\n *  0-7 0.16000\n *  1.81000\n *\n *  % java PrimMST mediumEWG.txt\n *  1-72   0.06506\n *  2-86   0.05980\n *  3-67   0.09725\n *  4-55   0.06425\n *  5-102  0.03834\n *  6-129  0.05363\n *  7-157  0.00516\n *  ...\n *  10.46351\n *\n *  % java PrimMST largeEWG.txt\n *  ...\n *  647.66307\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code PrimMST} class represents a data type for computing a\n *  <em>minimum spanning tree</em> in an edge-weighted graph.\n *  The edge weights can be positive, zero, or negative and need not\n *  be distinct. If the graph is not connected, it computes a <em>minimum\n *  spanning forest</em>, which is the union of minimum spanning trees\n *  in each connected component. The {@code weight()} method returns the\n *  weight of a minimum spanning tree and the {@code edges()} method\n *  returns its edges.\n *  <p>\n *  This implementation uses <em>Prim's algorithm</em> with an indexed\n *  binary heap.\n *  The constructor takes &Theta;(<em>E</em> log <em>V</em>) time in\n *  the worst case, where <em>V</em> is the number of\n *  vertices and <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the\n *  edge-weighted graph).\n *  <p>\n *  This {@code weight()} method correctly computes the weight of the MST\n *  if all arithmetic performed is without floating-point rounding error\n *  or arithmetic overflow.\n *  This is the case if all edge weights are non-negative integers\n *  and the weight of the MST does not exceed 2<sup>52</sup>.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/43mst\">Section 4.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For alternate implementations, see {@link LazyPrimMST}, {@link KruskalMST},\n *  and {@link BoruvkaMST}.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class PrimMST {\n    private static final double FLOATING_POINT_EPSILON = 1.0E-12;\n\n    private Edge[] edgeTo;        // edgeTo[v] = shortest edge from tree vertex to non-tree vertex\n    private double[] distTo;      // distTo[v] = weight of shortest such edge\n    private boolean[] marked;     // marked[v] = true if v on tree, false otherwise\n    private IndexMinPQ<Double> pq;\n\n    /**\n     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.\n     * @param graph the edge-weighted graph\n     */\n    public PrimMST(EdgeWeightedGraph graph) {\n        edgeTo = new Edge[graph.V()];\n        distTo = new double[graph.V()];\n        marked = new boolean[graph.V()];\n        pq = new IndexMinPQ<Double>(graph.V());\n        for (int v = 0; v < graph.V(); v++)\n            distTo[v] = Double.POSITIVE_INFINITY;\n\n        for (int v = 0; v < graph.V(); v++)      // run from each vertex to find\n            if (!marked[v]) prim(graph, v);      // minimum spanning forest\n\n        // check optimality conditions\n        assert check(graph);\n    }\n\n    // run Prim's algorithm in graph, starting from vertex s\n    private void prim(EdgeWeightedGraph graph, int s) {\n        distTo[s] = 0.0;\n        pq.insert(s, distTo[s]);\n        while (!pq.isEmpty()) {\n            int v = pq.delMin();\n            scan(graph, v);\n        }\n    }\n\n    // scan vertex v\n    private void scan(EdgeWeightedGraph graph, int v) {\n        marked[v] = true;\n        for (Edge e : graph.adj(v)) {\n            int w = e.other(v);\n            if (marked[w]) continue;         // v-w is obsolete edge\n            if (e.weight() < distTo[w]) {\n                distTo[w] = e.weight();\n                edgeTo[w] = e;\n                if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);\n                else                pq.insert(w, distTo[w]);\n            }\n        }\n    }\n\n    /**\n     * Returns the edges in a minimum spanning tree (or forest).\n     * @return the edges in a minimum spanning tree (or forest) as\n     *    an iterable of edges\n     */\n    public Iterable<Edge> edges() {\n        Queue<Edge> mst = new Queue<Edge>();\n        for (int v = 0; v < edgeTo.length; v++) {\n            Edge e = edgeTo[v];\n            if (e != null) {\n                mst.enqueue(e);\n            }\n        }\n        return mst;\n    }\n\n    /**\n     * Returns the sum of the edge weights in a minimum spanning tree (or forest).\n     * @return the sum of the edge weights in a minimum spanning tree (or forest)\n     */\n    public double weight() {\n        double weight = 0.0;\n        for (Edge e : edges())\n            weight += e.weight();\n        return weight;\n    }\n\n\n    // check optimality conditions (takes time proportional to E V lg* V)\n    private boolean check(EdgeWeightedGraph graph) {\n\n        // check weight\n        double totalWeight = 0.0;\n        for (Edge e : edges()) {\n            totalWeight += e.weight();\n        }\n        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {\n            System.err.printf(\"Weight of edges does not equal weight(): %f vs. %f\\n\", totalWeight, weight());\n            return false;\n        }\n\n        // check that it is acyclic\n        UF uf = new UF(graph.V());\n        for (Edge e : edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) == uf.find(w)) {\n                System.err.println(\"Not a forest\");\n                return false;\n            }\n            uf.union(v, w);\n        }\n\n        // check that it is a spanning forest\n        for (Edge e : graph.edges()) {\n            int v = e.either(), w = e.other(v);\n            if (uf.find(v) != uf.find(w)) {\n                System.err.println(\"Not a spanning forest\");\n                return false;\n            }\n        }\n\n        // check that it is a minimal spanning forest (cut optimality conditions)\n        for (Edge e : edges()) {\n\n            // all edges in MST except e\n            uf = new UF(graph.V());\n            for (Edge f : edges()) {\n                int x = f.either(), y = f.other(x);\n                if (f != e) uf.union(x, y);\n            }\n\n            // check that e is min weight edge in crossing cut\n            for (Edge f : graph.edges()) {\n                int x = f.either(), y = f.other(x);\n                if (uf.find(x) != uf.find(y)) {\n                    if (f.weight() < e.weight()) {\n                        System.err.println(\"Edge \" + f + \" violates cut optimality conditions\");\n                        return false;\n                    }\n                }\n            }\n\n        }\n\n        return true;\n    }\n\n    /**\n     * Unit tests the {@code PrimMST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        EdgeWeightedGraph graph = new EdgeWeightedGraph(in);\n        PrimMST mst = new PrimMST(graph);\n        for (Edge e : mst.edges()) {\n            StdOut.println(e);\n        }\n        StdOut.printf(\"%.5f\\n\", mst.weight());\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Queue.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Queue.java\n *  Execution:    java Queue < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/13stacks/tobe.txt\n *\n *  A generic queue, implemented using a linked list.\n *\n *  % java Queue < tobe.txt\n *  to be or not to be (2 left on queue)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code Queue} class represents a first-in-first-out (FIFO)\n *  queue of generic items.\n *  It supports the usual <em>enqueue</em> and <em>dequeue</em>\n *  operations, along with methods for peeking at the first item,\n *  testing if the queue is empty, and iterating through\n *  the items in FIFO order.\n *  <p>\n *  This implementation uses a singly linked list with a static nested class for\n *  linked-list nodes. See {@link LinkedQueue} for the version from the\n *  textbook that uses a non-static nested class.\n *  See {@link ResizingArrayQueue} for a version that uses a resizing array.\n *  The <em>enqueue</em>, <em>dequeue</em>, <em>peek</em>, <em>size</em>, and <em>is-empty</em>\n *  operations all take constant time in the worst case.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Item> the generic type of each item in this queue\n */\npublic class Queue<Item> implements Iterable<Item> {\n    private Node<Item> first;    // beginning of queue\n    private Node<Item> last;     // end of queue\n    private int n;               // number of elements on queue\n\n    // helper linked list class\n    private static class Node<Item> {\n        private Item item;\n        private Node<Item> next;\n    }\n\n    /**\n     * Initializes an empty queue.\n     */\n    public Queue() {\n        first = null;\n        last  = null;\n        n = 0;\n    }\n\n    /**\n     * Returns true if this queue is empty.\n     *\n     * @return {@code true} if this queue is empty; {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return first == null;\n    }\n\n    /**\n     * Returns the number of items in this queue.\n     *\n     * @return the number of items in this queue\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns the item least recently added to this queue.\n     *\n     * @return the item least recently added to this queue\n     * @throws NoSuchElementException if this queue is empty\n     */\n    public Item peek() {\n        if (isEmpty()) throw new NoSuchElementException(\"Queue underflow\");\n        return first.item;\n    }\n\n    /**\n     * Adds the item to this queue.\n     *\n     * @param  item the item to add\n     */\n    public void enqueue(Item item) {\n        Node<Item> oldlast = last;\n        last = new Node<Item>();\n        last.item = item;\n        last.next = null;\n        if (isEmpty()) first = last;\n        else           oldlast.next = last;\n        n++;\n    }\n\n    /**\n     * Removes and returns the item on this queue that was least recently added.\n     *\n     * @return the item on this queue that was least recently added\n     * @throws NoSuchElementException if this queue is empty\n     */\n    public Item dequeue() {\n        if (isEmpty()) throw new NoSuchElementException(\"Queue underflow\");\n        Item item = first.item;\n        first = first.next;\n        n--;\n        if (isEmpty()) last = null;   // to avoid loitering\n        return item;\n    }\n\n    /**\n     * Returns a string representation of this queue.\n     *\n     * @return the sequence of items in FIFO order, separated by spaces\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (Item item : this) {\n            s.append(item);\n            s.append(' ');\n        }\n        return s.toString();\n    }\n\n    /**\n     * Returns an iterator that iterates over the items in this queue in FIFO order.\n     *\n     * @return an iterator that iterates over the items in this queue in FIFO order\n     */\n    public Iterator<Item> iterator()  {\n        return new LinkedIterator(first);\n    }\n\n    // a linked-list iterator\n    private class LinkedIterator implements Iterator<Item> {\n        private Node<Item> current;\n\n        public LinkedIterator(Node<Item> first) {\n            current = first;\n        }\n\n        public boolean hasNext() {\n            return current != null;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = current.item;\n            current = current.next;\n            return item;\n        }\n    }\n\n\n    /**\n     * Unit tests the {@code Queue} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Queue<String> queue = new Queue<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\"))\n                queue.enqueue(item);\n            else if (!queue.isEmpty())\n                StdOut.print(queue.dequeue() + \" \");\n        }\n        StdOut.println(\"(\" + queue.size() + \" left on queue)\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Quick.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Quick.java\n *  Execution:    java Quick < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/23quicksort/tiny.txt\n *                https://algs4.cs.princeton.edu/23quicksort/words3.txt\n *\n *  Sorts a sequence of strings from standard input using quicksort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Quick < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Quick < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n *\n *  Remark: For a type-safe version that uses static generics, see\n *\n *    https://algs4.cs.princeton.edu/23quicksort/QuickPedantic.java\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Quick} class provides static methods for sorting an\n *  array and selecting the ith smallest element in an array using quicksort.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/23quicksort\">Section 2.3</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Quick {\n\n    // This class should not be instantiated.\n    private Quick() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        StdRandom.shuffle(a);\n        sort(a, 0, a.length - 1);\n        assert isSorted(a);\n    }\n\n    // quicksort the subarray from a[lo] to a[hi]\n    private static void sort(Comparable[] a, int lo, int hi) {\n        if (hi <= lo) return;\n        int j = partition(a, lo, hi);\n        sort(a, lo, j-1);\n        sort(a, j+1, hi);\n        assert isSorted(a, lo, hi);\n    }\n\n    // partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi]\n    // and return the index j.\n    private static int partition(Comparable[] a, int lo, int hi) {\n        int i = lo;\n        int j = hi + 1;\n        Comparable v = a[lo];\n        while (true) {\n\n            // find item on lo to swap\n            while (less(a[++i], v)) {\n                if (i == hi) break;\n            }\n\n            // find item on hi to swap\n            while (less(v, a[--j])) {\n                if (j == lo) break;      // redundant since a[lo] acts as sentinel\n            }\n\n            // check if pointers cross\n            if (i >= j) break;\n\n            exch(a, i, j);\n        }\n\n        // put partitioning item v at a[j]\n        exch(a, lo, j);\n\n        // now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]\n        return j;\n    }\n\n    /**\n     * Rearranges the array so that {@code a[k]} contains the kth smallest key;\n     * {@code a[0]} through {@code a[k-1]} are less than (or equal to) {@code a[k]}; and\n     * {@code a[k+1]} through {@code a[n-1]} are greater than (or equal to) {@code a[k]}.\n     *\n     * @param  a the array\n     * @param  k the rank of the key\n     * @return the key of rank {@code k}\n     * @throws IllegalArgumentException unless {@code 0 <= k < a.length}\n     */\n    public static Comparable select(Comparable[] a, int k) {\n        if (k < 0 || k >= a.length) {\n            throw new IllegalArgumentException(\"index is not between 0 and \" + a.length + \": \" + k);\n        }\n        StdRandom.shuffle(a);\n        int lo = 0, hi = a.length - 1;\n        while (hi > lo) {\n            int i = partition(a, lo, hi);\n            if      (i > k) hi = i - 1;\n            else if (i < k) lo = i + 1;\n            else return a[i];\n        }\n        return a[lo];\n    }\n\n\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        if (v == w) return false;   // optimization when reference equals\n        return v.compareTo(w) < 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length - 1);\n    }\n\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; quicksorts them;\n     * and prints them to standard output in ascending order.\n     * Shuffles the array and then prints the strings again to\n     * standard output, but this time, using the select method.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Quick.sort(a);\n        show(a);\n        assert isSorted(a);\n\n        // shuffle\n        StdRandom.shuffle(a);\n\n        // display results again using select\n        StdOut.println();\n        for (int i = 0; i < a.length; i++) {\n            String ith = (String) Quick.select(a, i);\n            StdOut.println(ith);\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Quick3string.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Quick3string.java\n *  Execution:    java Quick3string < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/51radix/words3.txt\n *                https://algs4.cs.princeton.edu/51radix/shells.txt\n *\n *  Reads string from standard input and 3-way string quicksort them.\n *\n *  % java Quick3string < shell.txt\n *  are\n *  by\n *  sea\n *  seashells\n *  seashells\n *  sells\n *  sells\n *  she\n *  she\n *  shells\n *  shore\n *  surely\n *  the\n *  the\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Quick3string} class provides static methods for sorting an\n *  array of strings using 3-way radix quicksort.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/51radix\">Section 5.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Quick3string {\n    private static final int CUTOFF =  15;   // cutoff to insertion sort\n\n    // do not instantiate\n    private Quick3string() { }\n\n    /**\n     * Rearranges the array of strings in ascending order.\n     *\n     * @param a the array to be sorted\n     */\n    public static void sort(String[] a) {\n        StdRandom.shuffle(a);\n        sort(a, 0, a.length-1, 0);\n        assert isSorted(a);\n    }\n\n    // return the dth character of s, -1 if d = length of s\n    private static int charAt(String s, int d) {\n        assert d >= 0 && d <= s.length();\n        if (d == s.length()) return -1;\n        return s.charAt(d);\n    }\n\n\n    // 3-way string quicksort a[lo..hi] starting at dth character\n    private static void sort(String[] a, int lo, int hi, int d) {\n\n        // cutoff to insertion sort for small subarrays\n        if (hi <= lo + CUTOFF) {\n            insertion(a, lo, hi, d);\n            return;\n        }\n\n        int lt = lo, gt = hi;\n        int v = charAt(a[lo], d);\n        int i = lo + 1;\n        while (i <= gt) {\n            int t = charAt(a[i], d);\n            if      (t < v) exch(a, lt++, i++);\n            else if (t > v) exch(a, i, gt--);\n            else              i++;\n        }\n\n        // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].\n        sort(a, lo, lt-1, d);\n        if (v >= 0) sort(a, lt, gt, d+1);\n        sort(a, gt+1, hi, d);\n    }\n\n    // sort from a[lo] to a[hi], starting at the dth character\n    private static void insertion(String[] a, int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1], d); j--)\n                exch(a, j, j-1);\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(String[] a, int i, int j) {\n        String temp = a[i];\n        a[i] = a[j];\n        a[j] = temp;\n    }\n\n    // is v less than w, starting at character d\n    // DEPRECATED BECAUSE OF SLOW SUBSTRING EXTRACTION IN JAVA 7\n    // private static boolean less(String v, String w, int d) {\n    //    assert v.substring(0, d).equals(w.substring(0, d));\n    //    return v.substring(d).compareTo(w.substring(d)) < 0;\n    // }\n\n    // is v less than w, starting at character d\n    private static boolean less(String v, String w, int d) {\n        assert v.substring(0, d).equals(w.substring(0, d));\n        for (int i = d; i < Math.min(v.length(), w.length()); i++) {\n            if (v.charAt(i) < w.charAt(i)) return true;\n            if (v.charAt(i) > w.charAt(i)) return false;\n        }\n        return v.length() < w.length();\n    }\n\n    // is the array sorted\n    private static boolean isSorted(String[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (a[i].compareTo(a[i-1]) < 0) return false;\n        return true;\n    }\n\n\n    /**\n     * Reads in a sequence of fixed-length strings from standard input;\n     * 3-way radix quicksorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read in the strings from standard input\n        String[] a = StdIn.readAllStrings();\n        int n = a.length;\n\n        // sort the strings\n        sort(a);\n\n        // print the results\n        for (int i = 0; i < n; i++)\n            StdOut.println(a[i]);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Quick3way.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Quick3way.java\n *  Execution:    java Quick3way < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/23quicksort/tiny.txt\n *                https://algs4.cs.princeton.edu/23quicksort/words3.txt\n *\n *  Sorts a sequence of strings from standard input using 3-way quicksort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Quick3way < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Quick3way < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Quick3way} class provides static methods for sorting an\n *  array using quicksort with 3-way partitioning.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/23quicksort\">Section 2.3</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Quick3way {\n\n    // This class should not be instantiated.\n    private Quick3way() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        StdRandom.shuffle(a);\n        sort(a, 0, a.length - 1);\n        assert isSorted(a);\n    }\n\n    // quicksort the subarray a[lo .. hi] using 3-way partitioning\n    private static void sort(Comparable[] a, int lo, int hi) {\n        if (hi <= lo) return;\n        int lt = lo, gt = hi;\n        Comparable v = a[lo];\n        int i = lo + 1;\n        while (i <= gt) {\n            int cmp = a[i].compareTo(v);\n            if      (cmp < 0) exch(a, lt++, i++);\n            else if (cmp > 0) exch(a, i, gt--);\n            else              i++;\n        }\n\n        // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].\n        sort(a, lo, lt-1);\n        sort(a, gt+1, hi);\n        assert isSorted(a, lo, hi);\n    }\n\n\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length - 1);\n    }\n\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; 3-way\n     * quicksorts them; and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Quick3way.sort(a);\n        show(a);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/QuickBentleyMcIlroy.java",
    "content": "/******************************************************************************\n *  Compilation:  javac QuickBentleyMcIlroy.java\n *  Execution:    java QuickBentleyMcIlroy < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/23quicksort/tiny.txt\n *                https://algs4.cs.princeton.edu/23quicksort/words3.txt\n *\n *  Uses the Bentley-McIlroy 3-way partitioning scheme,\n *  chooses the partitioning element using Tukey's ninther,\n *  and cuts off to insertion sort.\n *\n *  Reference: Engineering a Sort Function by Jon L. Bentley\n *  and M. Douglas McIlroy. Software-Practice and Experience,\n *  Vol. 23 (11), 1249-1265 (November 1993).\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code QuickBentleyMcIlroy} class provides static methods for sorting\n *  an array using an optimized version of quicksort (using Bentley-McIlroy\n *  3-way partitioning, Tukey's ninther, and cutoff to insertion sort).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/23quicksort\">Section 2.3</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class QuickBentleyMcIlroy {\n\n    // cutoff to insertion sort, must be >= 1\n    private static final int INSERTION_SORT_CUTOFF = 8;\n\n    // cutoff to median-of-3 partitioning\n    private static final int MEDIAN_OF_3_CUTOFF = 40;\n\n    // This class should not be instantiated.\n    private QuickBentleyMcIlroy() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        sort(a, 0, a.length - 1);\n    }\n\n    private static void sort(Comparable[] a, int lo, int hi) {\n        int n = hi - lo + 1;\n\n        // cutoff to insertion sort\n        if (n <= INSERTION_SORT_CUTOFF) {\n            insertionSort(a, lo, hi);\n            return;\n        }\n\n        // use median-of-3 as partitioning element\n        else if (n <= MEDIAN_OF_3_CUTOFF) {\n            int m = median3(a, lo, lo + n/2, hi);\n            exch(a, m, lo);\n        }\n\n        // use Tukey ninther as partitioning element\n        else  {\n            int eps = n/8;\n            int mid = lo + n/2;\n            int m1 = median3(a, lo, lo + eps, lo + eps + eps);\n            int m2 = median3(a, mid - eps, mid, mid + eps);\n            int m3 = median3(a, hi - eps - eps, hi - eps, hi);\n            int ninther = median3(a, m1, m2, m3);\n            exch(a, ninther, lo);\n        }\n\n        // Bentley-McIlroy 3-way partitioning\n        int i = lo, j = hi+1;\n        int p = lo, q = hi+1;\n        Comparable v = a[lo];\n        while (true) {\n            while (less(a[++i], v))\n                if (i == hi) break;\n            while (less(v, a[--j]))\n                if (j == lo) break;\n\n            // pointers cross\n            if (i == j && eq(a[i], v))\n                exch(a, ++p, i);\n            if (i >= j) break;\n\n            exch(a, i, j);\n            if (eq(a[i], v)) exch(a, ++p, i);\n            if (eq(a[j], v)) exch(a, --q, j);\n        }\n\n\n        i = j + 1;\n        for (int k = lo; k <= p; k++)\n            exch(a, k, j--);\n        for (int k = hi; k >= q; k--)\n            exch(a, k, i++);\n\n        sort(a, lo, j);\n        sort(a, i, hi);\n    }\n\n\n    // sort from a[lo] to a[hi] using insertion sort\n    private static void insertionSort(Comparable[] a, int lo, int hi) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(a[j], a[j-1]); j--)\n                exch(a, j, j-1);\n    }\n\n\n    // return the index of the median element among a[i], a[j], and a[k]\n    private static int median3(Comparable[] a, int i, int j, int k) {\n        return (less(a[i], a[j]) ?\n               (less(a[j], a[k]) ? j : less(a[i], a[k]) ? k : i) :\n               (less(a[k], a[j]) ? j : less(a[k], a[i]) ? k : i));\n    }\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        if (v == w) return false;    // optimization when reference equal\n        return v.compareTo(w) < 0;\n    }\n\n    // does v == w ?\n    private static boolean eq(Comparable v, Comparable w) {\n        if (v == w) return true;    // optimization when reference equal\n        return v.compareTo(w) == 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; quicksorts them\n     * (using an optimized version of quicksort);\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        QuickBentleyMcIlroy.sort(a);\n        assert isSorted(a);\n        show(a);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/QuickFindUF.java",
    "content": "/******************************************************************************\n *  Compilation:  javac QuickFindUF.java\n *  Execution:  java QuickFindUF < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/15uf/tinyUF.txt\n *                https://algs4.cs.princeton.edu/15uf/mediumUF.txt\n *                https://algs4.cs.princeton.edu/15uf/largeUF.txt\n *\n *  Quick-find algorithm.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code QuickFindUF} class represents a <em>union–find data type</em>\n *  (also known as the <em>disjoint-sets data type</em>).\n *  It supports the classic <em>union</em> and <em>find</em> operations,\n *  along with a <em>count</em> operation that returns the total number\n *  of sets.\n *  <p>\n *  The union–find data type models a collection of sets containing\n *  <em>n</em> elements, with each element in exactly one set.\n *  The elements are named 0 through <em>n</em>–1.\n *  Initially, there are <em>n</em> sets, with each element in its\n *  own set. The <em>canonical element</em> of a set\n *  (also known as the <em>root</em>, <em>identifier</em>,\n *  <em>leader</em>, or <em>set representative</em>)\n *  is one distinguished element in the set. Here is a summary of\n *  the operations:\n *  <ul>\n *  <li><em>find</em>(<em>p</em>) returns the canonical element\n *      of the set containing <em>p</em>. The <em>find</em> operation\n *      returns the same value for two elements if and only if\n *      they are in the same set.\n *  <li><em>union</em>(<em>p</em>, <em>q</em>) merges the set\n *      containing element <em>p</em> with the set containing\n *      element <em>q</em>. That is, if <em>p</em> and <em>q</em>\n *      are in different sets, replace these two sets\n *      with a new set that is the union of the two.\n *  <li><em>count</em>() returns the number of sets.\n *  </ul>\n *  <p>\n *  The canonical element of a set can change only when the set\n *  itself changes during a call to <em>union</em>&mdash;it cannot\n *  change during a call to either <em>find</em> or <em>count</em>.\n *  <p>\n *  This implementation uses <em>quick find</em>.\n *  The constructor takes &Theta;(<em>n</em>) time, where <em>n</em>\n *  is the number of sites.\n *  The <em>find</em>, <em>connected</em>, and <em>count</em>\n *  operations take &Theta;(1) time; the <em>union</em> operation\n *  takes &Theta;(<em>n</em>) time.\n *  <p>\n *  For alternative implementations of the same API, see\n *  {@link UF}, {@link QuickUnionUF}, and {@link WeightedQuickUnionUF}.\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/15uf\">Section 1.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class QuickFindUF {\n    private int[] id;    // id[i] = component identifier of i\n    private int count;   // number of components\n\n    /**\n     * Initializes an empty union-find data structure with\n     * {@code n} elements {@code 0} through {@code n-1}.\n     * Initially, each element is in its own set.\n     *\n     * @param  n the number of elements\n     * @throws IllegalArgumentException if {@code n < 0}\n     */\n    public QuickFindUF(int n) {\n        count = n;\n        id = new int[n];\n        for (int i = 0; i < n; i++)\n            id[i] = i;\n    }\n\n    /**\n     * Returns the number of sets.\n     *\n     * @return the number of sets (between {@code 1} and {@code n})\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Returns the canonical element of the set containing element {@code p}.\n     *\n     * @param  p an element\n     * @return the canonical element of the set containing {@code p}\n     * @throws IllegalArgumentException unless {@code 0 <= p < n}\n     */\n    public int find(int p) {\n        validate(p);\n        return id[p];\n    }\n\n    // validate that p is a valid index\n    private void validate(int p) {\n        int n = id.length;\n        if (p < 0 || p >= n) {\n            throw new IllegalArgumentException(\"index \" + p + \" is not between 0 and \" + (n-1));\n        }\n    }\n\n    /**\n     * Returns true if the two elements are in the same set.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @return {@code true} if {@code p} and {@code q} are in the same set;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     * @deprecated Replace with two calls to {@link #find(int)}.\n     */\n    @Deprecated\n    public boolean connected(int p, int q) {\n        validate(p);\n        validate(q);\n        return id[p] == id[q];\n    }\n\n    /**\n     * Merges the set containing element {@code p} with the set\n     * containing element {@code q}.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     */\n    public void union(int p, int q) {\n        validate(p);\n        validate(q);\n        int pID = id[p];   // needed for correctness\n        int qID = id[q];   // to reduce the number of array accesses\n\n        // p and q are already in the same component\n        if (pID == qID) return;\n\n        for (int i = 0; i < id.length; i++)\n            if (id[i] == pID) id[i] = qID;\n        count--;\n    }\n\n    /**\n     * Reads an integer {@code n} and a sequence of pairs of integers\n     * (between {@code 0} and {@code n-1}) from standard input, where each integer\n     * in the pair represents some element;\n     * if the elements are in different sets, merge the two sets\n     * and print the pair to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        QuickFindUF uf = new QuickFindUF(n);\n        while (!StdIn.isEmpty()) {\n            int p = StdIn.readInt();\n            int q = StdIn.readInt();\n            if (uf.find(p) == uf.find(q)) continue;\n            uf.union(p, q);\n            StdOut.println(p + \" \" + q);\n        }\n        StdOut.println(uf.count() + \" components\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/QuickUnionUF.java",
    "content": "/******************************************************************************\n *  Compilation:  javac QuickUnionUF.java\n *  Execution:  java QuickUnionUF < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/15uf/tinyUF.txt\n *                https://algs4.cs.princeton.edu/15uf/mediumUF.txt\n *                https://algs4.cs.princeton.edu/15uf/largeUF.txt\n *\n *  Quick-union algorithm.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code QuickUnionUF} class represents a <em>union–find data type</em>\n *  (also known as the <em>disjoint-sets data type</em>).\n *  It supports the classic <em>union</em> and <em>find</em> operations,\n *  along with a <em>count</em> operation that returns the total number\n *  of sets.\n *  <p>\n *  The union–find data type models a collection of sets containing\n *  <em>n</em> elements, with each element in exactly one set.\n *  The elements are named 0 through <em>n</em>–1.\n *  Initially, there are <em>n</em> sets, with each element in its\n *  own set. The <em>canonical element</em> of a set\n *  (also known as the <em>root</em>, <em>identifier</em>,\n *  <em>leader</em>, or <em>set representative</em>)\n *  is one distinguished element in the set. Here is a summary of\n *  the operations:\n *  <ul>\n *  <li><em>find</em>(<em>p</em>) returns the canonical element\n *      of the set containing <em>p</em>. The <em>find</em> operation\n *      returns the same value for two elements if and only if\n *      they are in the same set.\n *  <li><em>union</em>(<em>p</em>, <em>q</em>) merges the set\n *      containing element <em>p</em> with the set containing\n *      element <em>q</em>. That is, if <em>p</em> and <em>q</em>\n *      are in different sets, replace these two sets\n *      with a new set that is the union of the two.\n *  <li><em>count</em>() returns the number of sets.\n *  </ul>\n *  <p>\n *  The canonical element of a set can change only when the set\n *  itself changes during a call to <em>union</em>&mdash;it cannot\n *  change during a call to either <em>find</em> or <em>count</em>.\n *  <p>\n *  This implementation uses <em>quick union</em>.\n *  The constructor takes &Theta;(<em>n</em>) time, where\n *  <em>n</em> is the number of sites.\n *  The <em>union</em> and <em>find</em> operations take\n *  &Theta;(<em>n</em>) time in the worst case.\n *  The <em>count</em> operation takes &Theta;(1) time.\n *  <p>\n *  For alternative implementations of the same API, see\n *  {@link UF}, {@link QuickFindUF}, and {@link WeightedQuickUnionUF}.\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/15uf\">Section 1.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class QuickUnionUF {\n    private int[] parent;  // parent[i] = parent of i\n    private int count;     // number of components\n\n    /**\n     * Initializes an empty union-find data structure with\n     * {@code n} elements {@code 0} through {@code n-1}.\n     * Initially, each element is in its own set.\n     *\n     * @param  n the number of elements\n     * @throws IllegalArgumentException if {@code n < 0}\n     */\n    public QuickUnionUF(int n) {\n        parent = new int[n];\n        count = n;\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n        }\n    }\n\n    /**\n     * Returns the number of sets.\n     *\n     * @return the number of sets (between {@code 1} and {@code n})\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Returns the canonical element of the set containing element {@code p}.\n     *\n     * @param  p an element\n     * @return the canonical element of the set containing {@code p}\n     * @throws IllegalArgumentException unless {@code 0 <= p < n}\n     */\n    public int find(int p) {\n        validate(p);\n        while (p != parent[p])\n            p = parent[p];\n        return p;\n    }\n\n    // validate that p is a valid index\n    private void validate(int p) {\n        int n = parent.length;\n        if (p < 0 || p >= n) {\n            throw new IllegalArgumentException(\"index \" + p + \" is not between 0 and \" + (n-1));\n        }\n    }\n\n    /**\n     * Returns true if the two elements are in the same set.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @return {@code true} if {@code p} and {@code q} are in the same set;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     * @deprecated Replace with two calls to {@link #find(int)}.\n     */\n    @Deprecated\n    public boolean connected(int p, int q) {\n        return find(p) == find(q);\n    }\n\n    /**\n     * Merges the set containing element {@code p} with the set\n     * containing element {@code q}.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     */\n    public void union(int p, int q) {\n        int rootP = find(p);\n        int rootQ = find(q);\n        if (rootP == rootQ) return;\n        parent[rootP] = rootQ;\n        count--;\n    }\n\n    /**\n     * Reads an integer {@code n} and a sequence of pairs of integers\n     * (between {@code 0} and {@code n-1}) from standard input, where each integer\n     * in the pair represents some element;\n     * if the elements are in different sets, merge the two sets\n     * and print the pair to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        QuickUnionUF uf = new QuickUnionUF(n);\n        while (!StdIn.isEmpty()) {\n            int p = StdIn.readInt();\n            int q = StdIn.readInt();\n            if (uf.find(p) == uf.find(q)) continue;\n            uf.union(p, q);\n            StdOut.println(p + \" \" + q);\n        }\n        StdOut.println(uf.count() + \" components\");\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/QuickX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac QuickX.java\n *  Execution:    java QuickX < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/23quicksort/tiny.txt\n *                https://algs4.cs.princeton.edu/23quicksort/words3.txt\n *\n *  Uses the Hoare's 2-way partitioning scheme, chooses the partitioning\n *  element using median-of-3, and cuts off to insertion sort.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code QuickX} class provides static methods for sorting an array\n *  using an optimized version of quicksort (using Hoare's 2-way partitioning\n *  algorithm, median-of-3 to choose the partitioning element, and cutoff\n *  to insertion sort).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/23quicksort\">Section 2.3</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class QuickX {\n\n    // cutoff to insertion sort, must be >= 1\n    private static final int INSERTION_SORT_CUTOFF = 8;\n\n    // This class should not be instantiated.\n    private QuickX() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        // StdRandom.shuffle(a);\n        sort(a, 0, a.length - 1);\n        assert isSorted(a);\n    }\n\n    // quicksort the subarray from a[lo] to a[hi]\n    private static void sort(Comparable[] a, int lo, int hi) {\n        if (hi <= lo) return;\n\n        // cutoff to insertion sort (Insertion.sort() uses half-open intervals)\n        int n = hi - lo + 1;\n        if (n <= INSERTION_SORT_CUTOFF) {\n            Insertion.sort(a, lo, hi + 1);\n            return;\n        }\n\n        int j = partition(a, lo, hi);\n        sort(a, lo, j-1);\n        sort(a, j+1, hi);\n    }\n\n    // partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi]\n    // and return the index j.\n    private static int partition(Comparable[] a, int lo, int hi) {\n        int n = hi - lo + 1;\n        int m = median3(a, lo, lo + n/2, hi);\n        exch(a, m, lo);\n\n        int i = lo;\n        int j = hi + 1;\n        Comparable v = a[lo];\n\n        // a[lo] is unique largest element\n        while (less(a[++i], v)) {\n            if (i == hi) { exch(a, lo, hi); return hi; }\n        }\n\n        // a[lo] is unique smallest element\n        while (less(v, a[--j])) {\n            if (j == lo + 1) return lo;\n        }\n\n        // the main loop\n        while (i < j) {\n            exch(a, i, j);\n            while (less(a[++i], v)) ;\n            while (less(v, a[--j])) ;\n        }\n\n        // put partitioning item v at a[j]\n        exch(a, lo, j);\n\n        // now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]\n        return j;\n    }\n\n    // return the index of the median element among a[i], a[j], and a[k]\n    private static int median3(Comparable[] a, int i, int j, int k) {\n        return (less(a[i], a[j]) ?\n               (less(a[j], a[k]) ? j : less(a[i], a[k]) ? k : i) :\n               (less(a[k], a[j]) ? j : less(a[k], a[i]) ? k : i));\n    }\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; quicksorts them\n     * (using an optimized version of 2-way quicksort);\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        QuickX.sort(a);\n        assert isSorted(a);\n        show(a);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/RabinKarp.java",
    "content": "/******************************************************************************\n *  Compilation:  javac RabinKarp.java\n *  Execution:    java RabinKarp pat txt\n *  Dependencies: StdOut.java\n *\n *  Reads in two strings, the pattern and the input text, and\n *  searches for the pattern in the input text using the\n *  Las Vegas version of the Rabin-Karp algorithm.\n *\n *  % java RabinKarp abracadabra abacadabrabracabracadabrabrabracad\n *  pattern: abracadabra\n *  text:    abacadabrabracabracadabrabrabracad\n *  match:                 abracadabra\n *\n *  % java RabinKarp rab abacadabrabracabracadabrabrabracad\n *  pattern: rab\n *  text:    abacadabrabracabracadabrabrabracad\n *  match:           rab\n *\n *  % java RabinKarp bcara abacadabrabracabracadabrabrabracad\n *  pattern: bcara\n *  text:         abacadabrabracabracadabrabrabracad\n *\n *  %  java RabinKarp rabrabracad abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern:                        rabrabracad\n *\n *  % java RabinKarp abacad abacadabrabracabracadabrabrabracad\n *  text:    abacadabrabracabracadabrabrabracad\n *  pattern: abacad\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.math.BigInteger;\nimport java.util.Random;\n\n/**\n *  The {@code RabinKarp} class finds the first occurrence of a pattern string\n *  in a text string.\n *  <p>\n *  This implementation uses the Rabin-Karp algorithm.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/53substring\">Section 5.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class RabinKarp {\n    private String pat;      // the pattern  // needed only for Las Vegas\n    private long patHash;    // pattern hash value\n    private int m;           // pattern length\n    private long q;          // a large prime, small enough to avoid long overflow\n    private int R;           // radix\n    private long RM;         // R^(M-1) % Q\n\n    /**\n     * Preprocesses the pattern string.\n     *\n     * @param pattern the pattern string\n     * @param R the alphabet size\n     */\n    public RabinKarp(char[] pattern, int R) {\n        this.pat = String.valueOf(pattern);\n        this.R = R;\n        throw new UnsupportedOperationException(\"Operation not supported yet\");\n    }\n\n    /**\n     * Preprocesses the pattern string.\n     *\n     * @param pat the pattern string\n     */\n    public RabinKarp(String pat) {\n        this.pat = pat;      // save pattern (needed only for Las Vegas)\n        R = 256;\n        m = pat.length();\n        q = longRandomPrime();\n\n        // precompute R^(m-1) % q for use in removing leading digit\n        RM = 1;\n        for (int i = 1; i <= m-1; i++)\n            RM = (R * RM) % q;\n        patHash = hash(pat, m);\n    }\n\n    // Compute hash for key[0..m-1].\n    private long hash(String key, int m) {\n        long h = 0;\n        for (int j = 0; j < m; j++)\n            h = (R * h + key.charAt(j)) % q;\n        return h;\n    }\n\n    // Las Vegas version: does pat[] match txt[i..i-m+1] ?\n    private boolean check(String txt, int i) {\n        for (int j = 0; j < m; j++)\n            if (pat.charAt(j) != txt.charAt(i + j))\n                return false;\n        return true;\n    }\n\n    // Monte Carlo version: always return true\n    // private boolean check(int i) {\n    //    return true;\n    //}\n\n    /**\n     * Returns the index of the first occurrence of the pattern string\n     * in the text string.\n     *\n     * @param  txt the text string\n     * @return the index of the first occurrence of the pattern string\n     *         in the text string; n if no such match\n     */\n    public int search(String txt) {\n        int n = txt.length();\n        if (n < m) return n;\n        long txtHash = hash(txt, m);\n\n        // check for match at offset 0\n        if ((patHash == txtHash) && check(txt, 0))\n            return 0;\n\n        // check for hash match; if hash match, check for exact match\n        for (int i = m; i < n; i++) {\n            // Remove leading digit, add trailing digit, check for match.\n            txtHash = (txtHash + q - RM*txt.charAt(i-m) % q) % q;\n            txtHash = (txtHash*R + txt.charAt(i)) % q;\n\n            // match\n            int offset = i - m + 1;\n            if ((patHash == txtHash) && check(txt, offset))\n                return offset;\n        }\n\n        // no match\n        return n;\n    }\n\n\n    // a random 31-bit prime\n    private static long longRandomPrime() {\n        BigInteger prime = BigInteger.probablePrime(31, new Random());\n        return prime.longValue();\n    }\n\n    /**\n     * Takes a pattern string and an input string as command-line arguments;\n     * searches for the pattern string in the text string; and prints\n     * the first occurrence of the pattern string in the text string.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String pat = args[0];\n        String txt = args[1];\n\n        RabinKarp searcher = new RabinKarp(pat);\n        int offset = searcher.search(txt);\n\n        // print results\n        StdOut.println(\"text:    \" + txt);\n\n        // from brute force search method 1\n        StdOut.print(\"pattern: \");\n        for (int i = 0; i < offset; i++)\n            StdOut.print(\" \");\n        StdOut.println(pat);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/RandomSeq.java",
    "content": "/******************************************************************************\n *  Compilation:  javac RandomSeq.java\n *  Execution:    java RandomSeq n lo hi\n *  Dependencies: StdOut.java\n *\n *  Prints N numbers between lo and hi.\n *\n *  % java RandomSeq 5 100.0 200.0\n *  123.43\n *  153.13\n *  144.38\n *  155.18\n *  104.02\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code RandomSeq} class is a client that prints out a pseudorandom\n *  sequence of real numbers in a given range.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/11model\">Section 1.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class RandomSeq {\n\n    // this class should not be instantiated\n    private RandomSeq() { }\n\n\n    /**\n     * Reads in two command-line arguments lo and hi and prints n uniformly\n     * random real numbers in [lo, hi) to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // command-line arguments\n        int n = Integer.parseInt(args[0]);\n\n        // for backward compatibility with Intro to Programming in Java version of RandomSeq\n        if (args.length == 1) {\n            // generate and print n numbers between 0.0 and 1.0\n            for (int i = 0; i < n; i++) {\n                double x = StdRandom.uniformDouble(0.0, 1.0);\n                StdOut.println(x);\n            }\n        }\n\n        else if (args.length == 3) {\n            double lo = Double.parseDouble(args[1]);\n            double hi = Double.parseDouble(args[2]);\n\n            // generate and print n numbers between lo and hi\n            for (int i = 0; i < n; i++) {\n                double x = StdRandom.uniformDouble(lo, hi);\n                StdOut.printf(\"%.2f\\n\", x);\n            }\n        }\n\n        else {\n            throw new IllegalArgumentException(\"Invalid number of arguments\");\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/RectHV.java",
    "content": "/******************************************************************************\n *  Compilation:  javac RectHV.java\n *  Execution:    none\n *  Dependencies: Point2D.java\n *\n *  Immutable data type for 2D axis-aligned rectangle.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code RectHV} class is an immutable data type to encapsulate a\n *  two-dimensional axis-aligned rectagle with real-value coordinates.\n *  The rectangle is <em>closed</em>—it includes the points on the boundary.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic final class RectHV {\n    private final double xmin, ymin;   // minimum x- and y-coordinates\n    private final double xmax, ymax;   // maximum x- and y-coordinates\n\n    /**\n     * Initializes a new rectangle [<em>xmin</em>, <em>xmax</em>]\n     * x [<em>ymin</em>, <em>ymax</em>].\n     *\n     * @param  xmin the <em>x</em>-coordinate of the lower-left endpoint\n     * @param  ymin the <em>y</em>-coordinate of the lower-left endpoint\n     * @param  xmax the <em>x</em>-coordinate of the upper-right endpoint\n     * @param  ymax the <em>y</em>-coordinate of the upper-right endpoint\n     * @throws IllegalArgumentException if any of {@code xmin},\n     *         {@code ymin}, {@code xmax}, or {@code ymax}\n     *         is {@code Double.NaN}.\n     * @throws IllegalArgumentException if {@code xmax < xmin} or {@code ymax < ymin}.\n     */\n    public RectHV(double xmin, double ymin, double xmax, double ymax) {\n        this.xmin = xmin;\n        this.ymin = ymin;\n        this.xmax = xmax;\n        this.ymax = ymax;\n        if (Double.isNaN(xmin) || Double.isNaN(xmax)) {\n            throw new IllegalArgumentException(\"x-coordinate is NaN: \" + toString());\n        }\n        if (Double.isNaN(ymin) || Double.isNaN(ymax)) {\n            throw new IllegalArgumentException(\"y-coordinate is NaN: \" + toString());\n        }\n        if (xmax < xmin) {\n            throw new IllegalArgumentException(\"xmax < xmin: \" + toString());\n        }\n        if (ymax < ymin) {\n            throw new IllegalArgumentException(\"ymax < ymin: \" + toString());\n        }\n    }\n\n    /**\n     * Returns the minimum <em>x</em>-coordinate of any point in this rectangle.\n     *\n     * @return the minimum <em>x</em>-coordinate of any point in this rectangle\n     */\n    public double xmin() {\n        return xmin;\n    }\n\n    /**\n     * Returns the maximum <em>x</em>-coordinate of any point in this rectangle.\n     *\n     * @return the maximum <em>x</em>-coordinate of any point in this rectangle\n     */\n    public double xmax() {\n        return xmax;\n    }\n\n    /**\n     * Returns the minimum <em>y</em>-coordinate of any point in this rectangle.\n     *\n     * @return the minimum <em>y</em>-coordinate of any point in this rectangle\n     */\n    public double ymin() {\n        return ymin;\n    }\n\n    /**\n     * Returns the maximum <em>y</em>-coordinate of any point in this rectangle.\n     *\n     * @return the maximum <em>y</em>-coordinate of any point in this rectangle\n     */\n    public double ymax() {\n        return ymax;\n    }\n\n    /**\n     * Returns the width of this rectangle.\n     *\n     * @return the width of this rectangle {@code xmax - xmin}\n     */\n    public double width() {\n        return xmax - xmin;\n    }\n\n    /**\n     * Returns the height of this rectangle.\n     *\n     * @return the height of this rectangle {@code ymax - ymin}\n     */\n    public double height() {\n        return ymax - ymin;\n    }\n\n    /**\n     * Returns true if the two rectangles intersect, and false otherwise.\n     * This includes <em>improper intersections</em> (at points on the\n     * boundary of each rectangle) and <em>nested intersections</em>\n     * (when one rectangle is contained inside the other).\n     *\n     * @param  that the other rectangle\n     * @return {@code true} if this rectangle intersects the argument\n               rectangle at one or more points; false otherwise\n     */\n    public boolean intersects(RectHV that) {\n        return this.xmax >= that.xmin && this.ymax >= that.ymin\n            && that.xmax >= this.xmin && that.ymax >= this.ymin;\n    }\n\n    /**\n     * Returns true if this rectangle contains the point, and false otherwise.\n     * This includes point on the boundary of the rectangle.\n     * @param  p the point\n     * @return {@code true} if this rectangle contains the point {@code p},\n               possibly at the boundary; {@code false} otherwise\n     */\n    public boolean contains(Point2D p) {\n        return (p.x() >= xmin) && (p.x() <= xmax)\n            && (p.y() >= ymin) && (p.y() <= ymax);\n    }\n\n    /**\n     * Returns the Euclidean distance between this rectangle and the point {@code p}.\n     *\n     * @param  p the point\n     * @return the Euclidean distance between the point {@code p} and the closest point\n               on this rectangle; 0 if the point is contained in this rectangle\n     */\n    public double distanceTo(Point2D p) {\n        return Math.sqrt(this.distanceSquaredTo(p));\n    }\n\n    /**\n     * Returns the square of the Euclidean distance between this rectangle and the point {@code p}.\n     *\n     * @param  p the point\n     * @return the square of the Euclidean distance between the point {@code p} and\n     *         the closest point on this rectangle; 0 if the point is contained\n     *         in this rectangle\n     */\n    public double distanceSquaredTo(Point2D p) {\n        double dx = 0.0, dy = 0.0;\n        if      (p.x() < xmin) dx = p.x() - xmin;\n        else if (p.x() > xmax) dx = p.x() - xmax;\n        if      (p.y() < ymin) dy = p.y() - ymin;\n        else if (p.y() > ymax) dy = p.y() - ymax;\n        return dx*dx + dy*dy;\n    }\n\n    /**\n     * Compares this rectangle to the specified rectangle.\n     *\n     * @param  other the other rectangle\n     * @return {@code true} if this rectangle equals {@code other};\n     *         {@code false} otherwise\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        RectHV that = (RectHV) other;\n        if (this.xmin != that.xmin) return false;\n        if (this.ymin != that.ymin) return false;\n        if (this.xmax != that.xmax) return false;\n        if (this.ymax != that.ymax) return false;\n        return true;\n    }\n\n    /**\n     * Returns an integer hash code for this rectangle.\n     * @return an integer hash code for this rectangle\n     */\n    @Override\n    public int hashCode() {\n        int hash1 = ((Double) xmin).hashCode();\n        int hash2 = ((Double) ymin).hashCode();\n        int hash3 = ((Double) xmax).hashCode();\n        int hash4 = ((Double) ymax).hashCode();\n        return 31*(31*(31*hash1 + hash2) + hash3) + hash4;\n    }\n\n    /**\n     * Returns a string representation of this rectangle.\n     *\n     * @return a string representation of this rectangle, using the format\n     *         {@code [xmin, xmax] x [ymin, ymax]}\n     */\n    @Override\n    public String toString() {\n        return \"[\" + xmin + \", \" + xmax + \"] x [\" + ymin + \", \" + ymax + \"]\";\n    }\n\n    /**\n     * Draws this rectangle to standard draw.\n     */\n    public void draw() {\n        StdDraw.line(xmin, ymin, xmax, ymin);\n        StdDraw.line(xmax, ymin, xmax, ymax);\n        StdDraw.line(xmax, ymax, xmin, ymax);\n        StdDraw.line(xmin, ymax, xmin, ymin);\n    }\n\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/RedBlackBST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac RedBlackBST.java\n *  Execution:    java RedBlackBST < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/33balanced/tinyST.txt\n *\n *  A symbol table implemented using a left-leaning red-black BST.\n *  This is the 2-3 version.\n *\n *  Note: commented out assertions because DrJava now enables assertions\n *        by default.\n *\n *  % more tinyST.txt\n *  S E A R C H E X A M P L E\n *\n *  % java RedBlackBST < tinyST.txt\n *  A 8\n *  C 4\n *  E 12\n *  H 5\n *  L 11\n *  M 9\n *  P 10\n *  R 3\n *  S 0\n *  X 7\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code BST} class represents an ordered symbol table of generic\n *  key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides ordered methods for finding the <em>minimum</em>,\n *  <em>maximum</em>, <em>floor</em>, and <em>ceiling</em>.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  It requires that\n *  the key type implements the {@code Comparable} interface and calls the\n *  {@code compareTo()} and method to compare two keys. It does not call either\n *  {@code equals()} or {@code hashCode()}.\n *  <p>\n *  This implementation uses a <em>left-leaning red-black BST</em>.\n *  The <em>put</em>, <em>get</em>, <em>contains</em>, <em>remove</em>,\n *  <em>minimum</em>, <em>maximum</em>, <em>ceiling</em>, <em>floor</em>,\n *  <em>rank</em>, and <em>select</em> operations each take\n *  &Theta;(log <em>n</em>) time in the worst case, where <em>n</em> is the\n *  number of key-value pairs in the symbol table.\n *  The <em>size</em>, and <em>is-empty</em> operations take &Theta;(1) time.\n *  The <em>keys</em> methods take\n *  <em>O</em>(log <em>n</em> + <em>m</em>) time, where <em>m</em> is\n *  the number of keys returned by the iterator.\n *  Construction takes &Theta;(1) time.\n *  <p>\n *  For alternative implementations of the symbol table API, see {@link ST},\n *  {@link BinarySearchST}, {@link SequentialSearchST}, {@link BST},\n *  {@link SeparateChainingHashST}, {@link LinearProbingHashST}, and\n *  {@link AVLTreeST}.\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/33balanced\">Section 3.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class RedBlackBST<Key extends Comparable<Key>, Value> {\n\n    private static final boolean RED   = true;\n    private static final boolean BLACK = false;\n\n    private Node root;     // root of the BST\n\n    // BST helper node data type\n    private class Node {\n        private Key key;           // key\n        private Value val;         // associated data\n        private Node left, right;  // links to left and right subtrees\n        private boolean color;     // color of parent link\n        private int size;          // subtree count\n\n        public Node(Key key, Value val, boolean color, int size) {\n            this.key = key;\n            this.val = val;\n            this.color = color;\n            this.size = size;\n        }\n    }\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public RedBlackBST() {\n    }\n\n   /***************************************************************************\n    *  Node helper methods.\n    ***************************************************************************/\n    // is node x red; false if x is null ?\n    private boolean isRed(Node x) {\n        if (x == null) return false;\n        return x.color == RED;\n    }\n\n    // number of node in subtree rooted at x; 0 if x is null\n    private int size(Node x) {\n        if (x == null) return 0;\n        return x.size;\n    }\n\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return size(root);\n    }\n\n   /**\n     * Is this symbol table empty?\n     * @return {@code true} if this symbol table is empty and {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return root == null;\n    }\n\n\n   /***************************************************************************\n    *  Standard BST search.\n    ***************************************************************************/\n\n    /**\n     * Returns the value associated with the given key.\n     * @param key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *     and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        return get(root, key);\n    }\n\n    // value associated with the given key in subtree rooted at x; null if no such key\n    private Value get(Node x, Key key) {\n        while (x != null) {\n            int cmp = key.compareTo(x.key);\n            if      (cmp < 0) x = x.left;\n            else if (cmp > 0) x = x.right;\n            else              return x.val;\n        }\n        return null;\n    }\n\n    /**\n     * Does this symbol table contain the given key?\n     * @param key the key\n     * @return {@code true} if this symbol table contains {@code key} and\n     *     {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        return get(key) != null;\n    }\n\n   /***************************************************************************\n    *  Red-black tree insertion.\n    ***************************************************************************/\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param key the key\n     * @param val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n        if (val == null) {\n            delete(key);\n            return;\n        }\n\n        root = put(root, key, val);\n        root.color = BLACK;\n        // assert check();\n    }\n\n    // insert the key-value pair in the subtree rooted at h\n    private Node put(Node h, Key key, Value val) {\n        if (h == null) return new Node(key, val, RED, 1);\n\n        int cmp = key.compareTo(h.key);\n        if      (cmp < 0) h.left  = put(h.left,  key, val);\n        else if (cmp > 0) h.right = put(h.right, key, val);\n        else              h.val   = val;\n\n        // fix-up any right-leaning links\n        if (isRed(h.right) && !isRed(h.left))      h = rotateLeft(h);\n        if (isRed(h.left)  &&  isRed(h.left.left)) h = rotateRight(h);\n        if (isRed(h.left)  &&  isRed(h.right))     flipColors(h);\n        h.size = size(h.left) + size(h.right) + 1;\n\n        return h;\n    }\n\n   /***************************************************************************\n    *  Red-black tree deletion.\n    ***************************************************************************/\n\n    /**\n     * Removes the smallest key and associated value from the symbol table.\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMin() {\n        if (isEmpty()) throw new NoSuchElementException(\"BST underflow\");\n\n        // if both children of root are black, set root to red\n        if (!isRed(root.left) && !isRed(root.right))\n            root.color = RED;\n\n        root = deleteMin(root);\n        if (!isEmpty()) root.color = BLACK;\n        // assert check();\n    }\n\n    // delete the key-value pair with the minimum key rooted at h\n    private Node deleteMin(Node h) {\n        if (h.left == null)\n            return null;\n\n        if (!isRed(h.left) && !isRed(h.left.left))\n            h = moveRedLeft(h);\n\n        h.left = deleteMin(h.left);\n        return balance(h);\n    }\n\n\n    /**\n     * Removes the largest key and associated value from the symbol table.\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public void deleteMax() {\n        if (isEmpty()) throw new NoSuchElementException(\"BST underflow\");\n\n        // if both children of root are black, set root to red\n        if (!isRed(root.left) && !isRed(root.right))\n            root.color = RED;\n\n        root = deleteMax(root);\n        if (!isEmpty()) root.color = BLACK;\n        // assert check();\n    }\n\n    // delete the key-value pair with the maximum key rooted at h\n    private Node deleteMax(Node h) {\n        if (isRed(h.left))\n            h = rotateRight(h);\n\n        if (h.right == null)\n            return null;\n\n        if (!isRed(h.right) && !isRed(h.right.left))\n            h = moveRedRight(h);\n\n        h.right = deleteMax(h.right);\n\n        return balance(h);\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        if (!contains(key)) return;\n\n        // if both children of root are black, set root to red\n        if (!isRed(root.left) && !isRed(root.right))\n            root.color = RED;\n\n        root = delete(root, key);\n        if (!isEmpty()) root.color = BLACK;\n        // assert check();\n    }\n\n    // delete the key-value pair with the given key rooted at h\n    private Node delete(Node h, Key key) {\n        // assert get(h, key) != null;\n\n        if (key.compareTo(h.key) < 0)  {\n            if (!isRed(h.left) && !isRed(h.left.left))\n                h = moveRedLeft(h);\n            h.left = delete(h.left, key);\n        }\n        else {\n            if (isRed(h.left))\n                h = rotateRight(h);\n            if (key.compareTo(h.key) == 0 && (h.right == null))\n                return null;\n            if (!isRed(h.right) && !isRed(h.right.left))\n                h = moveRedRight(h);\n            if (key.compareTo(h.key) == 0) {\n                Node x = min(h.right);\n                h.key = x.key;\n                h.val = x.val;\n                // h.val = get(h.right, min(h.right).key);\n                // h.key = min(h.right).key;\n                h.right = deleteMin(h.right);\n            }\n            else h.right = delete(h.right, key);\n        }\n        return balance(h);\n    }\n\n   /***************************************************************************\n    *  Red-black tree helper functions.\n    ***************************************************************************/\n\n    // make a left-leaning link lean to the right\n    private Node rotateRight(Node h) {\n        assert (h != null) && isRed(h.left);\n        // assert (h != null) && isRed(h.left) &&  !isRed(h.right);  // for insertion only\n        Node x = h.left;\n        h.left = x.right;\n        x.right = h;\n        x.color = h.color;\n        h.color = RED;\n        x.size = h.size;\n        h.size = size(h.left) + size(h.right) + 1;\n        return x;\n    }\n\n    // make a right-leaning link lean to the left\n    private Node rotateLeft(Node h) {\n        assert (h != null) && isRed(h.right);\n        // assert (h != null) && isRed(h.right) && !isRed(h.left);  // for insertion only\n        Node x = h.right;\n        h.right = x.left;\n        x.left = h;\n        x.color = h.color;\n        h.color = RED;\n        x.size = h.size;\n        h.size = size(h.left) + size(h.right) + 1;\n        return x;\n    }\n\n    // flip the colors of a node and its two children\n    private void flipColors(Node h) {\n        // h must have opposite color of its two children\n        // assert (h != null) && (h.left != null) && (h.right != null);\n        // assert (!isRed(h) &&  isRed(h.left) &&  isRed(h.right))\n        //    || (isRed(h)  && !isRed(h.left) && !isRed(h.right));\n        h.color = !h.color;\n        h.left.color = !h.left.color;\n        h.right.color = !h.right.color;\n    }\n\n    // Assuming that h is red and both h.left and h.left.left\n    // are black, make h.left or one of its children red.\n    private Node moveRedLeft(Node h) {\n        // assert (h != null);\n        // assert isRed(h) && !isRed(h.left) && !isRed(h.left.left);\n\n        flipColors(h);\n        if (isRed(h.right.left)) {\n            h.right = rotateRight(h.right);\n            h = rotateLeft(h);\n            flipColors(h);\n        }\n        return h;\n    }\n\n    // Assuming that h is red and both h.right and h.right.left\n    // are black, make h.right or one of its children red.\n    private Node moveRedRight(Node h) {\n        // assert (h != null);\n        // assert isRed(h) && !isRed(h.right) && !isRed(h.right.left);\n        flipColors(h);\n        if (isRed(h.left.left)) {\n            h = rotateRight(h);\n            flipColors(h);\n        }\n        return h;\n    }\n\n    // restore red-black tree invariant\n    private Node balance(Node h) {\n        // assert (h != null);\n\n        if (isRed(h.right) && !isRed(h.left))    h = rotateLeft(h);\n        if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h);\n        if (isRed(h.left) && isRed(h.right))     flipColors(h);\n\n        h.size = size(h.left) + size(h.right) + 1;\n        return h;\n    }\n\n\n   /***************************************************************************\n    *  Utility functions.\n    ***************************************************************************/\n\n    /**\n     * Returns the height of the BST (for debugging).\n     * @return the height of the BST (a 1-node tree has height 0)\n     */\n    public int height() {\n        return height(root);\n    }\n    private int height(Node x) {\n        if (x == null) return -1;\n        return 1 + Math.max(height(x.left), height(x.right));\n    }\n\n   /***************************************************************************\n    *  Ordered symbol table methods.\n    ***************************************************************************/\n\n    /**\n     * Returns the smallest key in the symbol table.\n     * @return the smallest key in the symbol table\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"calls min() with empty symbol table\");\n        return min(root).key;\n    }\n\n    // the smallest key in subtree rooted at x; null if no such key\n    private Node min(Node x) {\n        // assert x != null;\n        if (x.left == null) return x;\n        else                return min(x.left);\n    }\n\n    /**\n     * Returns the largest key in the symbol table.\n     * @return the largest key in the symbol table\n     * @throws NoSuchElementException if the symbol table is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"calls max() with empty symbol table\");\n        return max(root).key;\n    }\n\n    // the largest key in the subtree rooted at x; null if no such key\n    private Node max(Node x) {\n        // assert x != null;\n        if (x.right == null) return x;\n        else                 return max(x.right);\n    }\n\n\n    /**\n     * Returns the largest key in the symbol table less than or equal to {@code key}.\n     * @param key the key\n     * @return the largest key in the symbol table less than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key floor(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to floor() is null\");\n        if (isEmpty()) throw new NoSuchElementException(\"calls floor() with empty symbol table\");\n        Node x = floor(root, key);\n        if (x == null) throw new NoSuchElementException(\"argument to floor() is too small\");\n        else           return x.key;\n    }\n\n    // the largest key in the subtree rooted at x less than or equal to the given key\n    private Node floor(Node x, Key key) {\n        if (x == null) return null;\n        int cmp = key.compareTo(x.key);\n        if (cmp == 0) return x;\n        if (cmp < 0)  return floor(x.left, key);\n        Node t = floor(x.right, key);\n        if (t != null) return t;\n        else           return x;\n    }\n\n    /**\n     * Returns the smallest key in the symbol table greater than or equal to {@code key}.\n     * @param key the key\n     * @return the smallest key in the symbol table greater than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key ceiling(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to ceiling() is null\");\n        if (isEmpty()) throw new NoSuchElementException(\"calls ceiling() with empty symbol table\");\n        Node x = ceiling(root, key);\n        if (x == null) throw new NoSuchElementException(\"argument to ceiling() is too large\");\n        else           return x.key;\n    }\n\n    // the smallest key in the subtree rooted at x greater than or equal to the given key\n    private Node ceiling(Node x, Key key) {\n        if (x == null) return null;\n        int cmp = key.compareTo(x.key);\n        if (cmp == 0) return x;\n        if (cmp > 0)  return ceiling(x.right, key);\n        Node t = ceiling(x.left, key);\n        if (t != null) return t;\n        else           return x;\n    }\n\n    /**\n     * Return the key in the symbol table of a given {@code rank}.\n     * This key has the property that there are {@code rank} keys in\n     * the symbol table that are smaller. In other words, this key is the\n     * ({@code rank}+1)st smallest key in the symbol table.\n     *\n     * @param  rank the order statistic\n     * @return the key in the symbol table of given {@code rank}\n     * @throws IllegalArgumentException unless {@code rank} is between 0 and\n     *        <em>n</em>–1\n     */\n    public Key select(int rank) {\n        if (rank < 0 || rank >= size()) {\n            throw new IllegalArgumentException(\"argument to select() is invalid: \" + rank);\n        }\n        return select(root, rank);\n    }\n\n    // Return key in BST rooted at x of given rank.\n    // Precondition: rank is in legal range.\n    private Key select(Node x, int rank) {\n        if (x == null) return null;\n        int leftSize = size(x.left);\n        if      (leftSize > rank) return select(x.left,  rank);\n        else if (leftSize < rank) return select(x.right, rank - leftSize - 1);\n        else                      return x.key;\n    }\n\n    /**\n     * Return the number of keys in the symbol table strictly less than {@code key}.\n     * @param key the key\n     * @return the number of keys in the symbol table strictly less than {@code key}\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public int rank(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to rank() is null\");\n        return rank(key, root);\n    }\n\n    // number of keys less than key in the subtree rooted at x\n    private int rank(Key key, Node x) {\n        if (x == null) return 0;\n        int cmp = key.compareTo(x.key);\n        if      (cmp < 0) return rank(key, x.left);\n        else if (cmp > 0) return 1 + size(x.left) + rank(key, x.right);\n        else              return size(x.left);\n    }\n\n   /***************************************************************************\n    *  Range count and range search.\n    ***************************************************************************/\n\n    /**\n     * Returns all keys in the symbol table in ascending order as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     * @return all keys in the symbol table in ascending order\n     */\n    public Iterable<Key> keys() {\n        if (isEmpty()) return new Queue<Key>();\n        return keys(min(), max());\n    }\n\n    /**\n     * Returns all keys in the symbol table in the given range in ascending order,\n     * as an {@code Iterable}.\n     *\n     * @param  lo minimum endpoint\n     * @param  hi maximum endpoint\n     * @return all keys in the symbol table between {@code lo}\n     *    (inclusive) and {@code hi} (inclusive) in ascending order\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *    is {@code null}\n     */\n    public Iterable<Key> keys(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to keys() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to keys() is null\");\n\n        Queue<Key> queue = new Queue<Key>();\n        // if (isEmpty() || lo.compareTo(hi) > 0) return queue;\n        keys(root, queue, lo, hi);\n        return queue;\n    }\n\n    // add the keys between lo and hi in the subtree rooted at x\n    // to the queue\n    private void keys(Node x, Queue<Key> queue, Key lo, Key hi) {\n        if (x == null) return;\n        int cmplo = lo.compareTo(x.key);\n        int cmphi = hi.compareTo(x.key);\n        if (cmplo < 0) keys(x.left, queue, lo, hi);\n        if (cmplo <= 0 && cmphi >= 0) queue.enqueue(x.key);\n        if (cmphi > 0) keys(x.right, queue, lo, hi);\n    }\n\n    /**\n     * Returns the number of keys in the symbol table in the given range.\n     *\n     * @param  lo minimum endpoint\n     * @param  hi maximum endpoint\n     * @return the number of keys in the symbol table between {@code lo}\n     *    (inclusive) and {@code hi} (inclusive)\n     * @throws IllegalArgumentException if either {@code lo} or {@code hi}\n     *    is {@code null}\n     */\n    public int size(Key lo, Key hi) {\n        if (lo == null) throw new IllegalArgumentException(\"first argument to size() is null\");\n        if (hi == null) throw new IllegalArgumentException(\"second argument to size() is null\");\n\n        if (lo.compareTo(hi) > 0) return 0;\n        if (contains(hi)) return rank(hi) - rank(lo) + 1;\n        else              return rank(hi) - rank(lo);\n    }\n\n\n   /***************************************************************************\n    *  Check integrity of red-black tree data structure.\n    ***************************************************************************/\n    private boolean check() {\n        if (!isBST())            StdOut.println(\"Not in symmetric order\");\n        if (!isSizeConsistent()) StdOut.println(\"Subtree counts not consistent\");\n        if (!isRankConsistent()) StdOut.println(\"Ranks not consistent\");\n        if (!is23())             StdOut.println(\"Not a 2-3 tree\");\n        if (!isBalanced())       StdOut.println(\"Not balanced\");\n        return isBST() && isSizeConsistent() && isRankConsistent() && is23() && isBalanced();\n    }\n\n    // does this binary tree satisfy symmetric order?\n    // Note: this test also ensures that data structure is a binary tree since order is strict\n    private boolean isBST() {\n        return isBST(root, null, null);\n    }\n\n    // is the tree rooted at x a BST with all keys strictly between min and max\n    // (if min or max is null, treat as empty constraint)\n    // Credit: elegant solution due to Bob Dondero\n    private boolean isBST(Node x, Key min, Key max) {\n        if (x == null) return true;\n        if (min != null && x.key.compareTo(min) <= 0) return false;\n        if (max != null && x.key.compareTo(max) >= 0) return false;\n        return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);\n    }\n\n    // are the size fields correct?\n    private boolean isSizeConsistent() { return isSizeConsistent(root); }\n    private boolean isSizeConsistent(Node x) {\n        if (x == null) return true;\n        if (x.size != size(x.left) + size(x.right) + 1) return false;\n        return isSizeConsistent(x.left) && isSizeConsistent(x.right);\n    }\n\n    // check that ranks are consistent\n    private boolean isRankConsistent() {\n        for (int i = 0; i < size(); i++)\n            if (i != rank(select(i))) return false;\n        for (Key key : keys())\n            if (key.compareTo(select(rank(key))) != 0) return false;\n        return true;\n    }\n\n    // Does the tree have no red right links, and at most one (left)\n    // red links in a row on any path?\n    private boolean is23() { return is23(root); }\n    private boolean is23(Node x) {\n        if (x == null) return true;\n        if (isRed(x.right)) return false;\n        if (x != root && isRed(x) && isRed(x.left))\n            return false;\n        return is23(x.left) && is23(x.right);\n    }\n\n    // do all paths from root to leaf have same number of black edges?\n    private boolean isBalanced() {\n        int black = 0;     // number of black links on path from root to min\n        Node x = root;\n        while (x != null) {\n            if (!isRed(x)) black++;\n            x = x.left;\n        }\n        return isBalanced(root, black);\n    }\n\n    // does every path from the root to a leaf have the given number of black links?\n    private boolean isBalanced(Node x, int black) {\n        if (x == null) return black == 0;\n        if (!isRed(x)) black--;\n        return isBalanced(x.left, black) && isBalanced(x.right, black);\n    }\n\n\n    /**\n     * Unit tests the {@code RedBlackBST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        RedBlackBST<String, Integer> st = new RedBlackBST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n        StdOut.println();\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n        StdOut.println();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ResizingArrayBag.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ResizingArrayBag.java\n *  Execution:    java ResizingArrayBag\n *  Dependencies: StdIn.java StdOut.java\n *\n *  Bag implementation with a resizing array.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code ResizingArrayBag} class represents a bag (or multiset) of\n *  generic items. It supports insertion and iterating over the\n *  items in arbitrary order.\n *  <p>\n *  This implementation uses a resizing array.\n *  See {@link LinkedBag} for a version that uses a singly linked list.\n *  The <em>add</em> operation takes constant amortized time; the\n *  <em>isEmpty</em>, and <em>size</em> operations\n *  take constant time. Iteration takes time proportional to the number of items.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class ResizingArrayBag<Item> implements Iterable<Item> {\n    // initial capacity of underlying resizing array\n    private static final int INIT_CAPACITY = 8;\n\n    private Item[] a;         // array of items\n    private int n;            // number of elements on bag\n\n    /**\n     * Initializes an empty bag.\n     */\n    public ResizingArrayBag() {\n        a = (Item[]) new Object[INIT_CAPACITY];\n        n = 0;\n    }\n\n    /**\n     * Is this bag empty?\n     * @return true if this bag is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Returns the number of items in this bag.\n     * @return the number of items in this bag\n     */\n    public int size() {\n        return n;\n    }\n\n    // resize the underlying array holding the elements\n    private void resize(int capacity) {\n        assert capacity >= n;\n        Item[] copy = (Item[]) new Object[capacity];\n        for (int i = 0; i < n; i++)\n            copy[i] = a[i];\n        a = copy;\n    }\n\n    /**\n     * Adds the item to this bag.\n     * @param item the item to add to this bag\n     */\n    public void add(Item item) {\n        if (n == a.length) resize(2*a.length);    // double size of array if necessary\n        a[n++] = item;                            // add item\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the items in the bag in arbitrary order.\n     * @return an iterator that iterates over the items in the bag in arbitrary order\n     */\n    public Iterator<Item> iterator() {\n        return new ArrayIterator();\n    }\n\n    // an array iterator\n    private class ArrayIterator implements Iterator<Item> {\n        private int i = 0;\n\n        public boolean hasNext() {\n            return i < n;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            return a[i++];\n        }\n    }\n\n    /**\n     * Unit tests the {@code ResizingArrayBag} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        ResizingArrayBag<String> bag = new ResizingArrayBag<String>();\n        bag.add(\"Hello\");\n        bag.add(\"World\");\n        bag.add(\"how\");\n        bag.add(\"are\");\n        bag.add(\"you\");\n\n        for (String s : bag)\n            StdOut.println(s);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ResizingArrayQueue.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ResizingArrayQueue.java\n *  Execution:    java ResizingArrayQueue < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/13stacks/tobe.txt\n *\n *  Queue implementation with a resizing array.\n *\n *  % java ResizingArrayQueue < tobe.txt\n *  to be or not to be (2 left on queue)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code ResizingArrayQueue} class represents a first-in-first-out (FIFO)\n *  queue of generic items.\n *  It supports the usual <em>enqueue</em> and <em>dequeue</em>\n *  operations, along with methods for peeking at the first item,\n *  testing if the queue is empty, and iterating through\n *  the items in FIFO order.\n *  <p>\n *  This implementation uses a resizing array, which double the underlying array\n *  when it is full and halves the underlying array when it is one-quarter full.\n *  The <em>enqueue</em> and <em>dequeue</em> operations take constant amortized time.\n *  The <em>size</em>, <em>peek</em>, and <em>is-empty</em> operations takes\n *  constant time in the worst case.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class ResizingArrayQueue<Item> implements Iterable<Item> {\n    // initial capacity of underlying resizing array\n    private static final int INIT_CAPACITY = 8;\n\n    private Item[] q;       // queue elements\n    private int n;          // number of elements on queue\n    private int first;      // index of first element of queue\n    private int last;       // index of next available slot\n\n\n    /**\n     * Initializes an empty queue.\n     */\n    public ResizingArrayQueue() {\n        q = (Item[]) new Object[INIT_CAPACITY];\n        n = 0;\n        first = 0;\n        last = 0;\n    }\n\n    /**\n     * Is this queue empty?\n     * @return true if this queue is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Returns the number of items in this queue.\n     * @return the number of items in this queue\n     */\n    public int size() {\n        return n;\n    }\n\n    // resize the underlying array\n    private void resize(int capacity) {\n        assert capacity >= n;\n        Item[] copy = (Item[]) new Object[capacity];\n        for (int i = 0; i < n; i++) {\n            copy[i] = q[(first + i) % q.length];\n        }\n        q = copy;\n        first = 0;\n        last  = n;\n    }\n\n    /**\n     * Adds the item to this queue.\n     * @param item the item to add\n     */\n    public void enqueue(Item item) {\n        // double size of array if necessary and recopy to front of array\n        if (n == q.length) resize(2*q.length);   // double size of array if necessary\n        q[last++] = item;                        // add item\n        if (last == q.length) last = 0;          // wrap-around\n        n++;\n    }\n\n    /**\n     * Removes and returns the item on this queue that was least recently added.\n     * @return the item on this queue that was least recently added\n     * @throws java.util.NoSuchElementException if this queue is empty\n     */\n    public Item dequeue() {\n        if (isEmpty()) throw new NoSuchElementException(\"Queue underflow\");\n        Item item = q[first];\n        q[first] = null;                            // to avoid loitering\n        n--;\n        first++;\n        if (first == q.length) first = 0;           // wrap-around\n        // shrink size of array if necessary\n        if (n > 0 && n == q.length/4) resize(q.length/2);\n        return item;\n    }\n\n    /**\n     * Returns the item least recently added to this queue.\n     * @return the item least recently added to this queue\n     * @throws java.util.NoSuchElementException if this queue is empty\n     */\n    public Item peek() {\n        if (isEmpty()) throw new NoSuchElementException(\"Queue underflow\");\n        return q[first];\n    }\n\n\n    /**\n     * Returns an iterator that iterates over the items in this queue in FIFO order.\n     * @return an iterator that iterates over the items in this queue in FIFO order\n     */\n    public Iterator<Item> iterator() {\n        return new ArrayIterator();\n    }\n\n    // an array iterator, from first to last-1\n    private class ArrayIterator implements Iterator<Item> {\n        private int i = 0;\n\n        public boolean hasNext() {\n            return i < n;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = q[(i + first) % q.length];\n            i++;\n            return item;\n        }\n    }\n\n   /**\n     * Unit tests the {@code ResizingArrayQueue} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        ResizingArrayQueue<String> queue = new ResizingArrayQueue<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\")) queue.enqueue(item);\n            else if (!queue.isEmpty()) StdOut.print(queue.dequeue() + \" \");\n        }\n        StdOut.println(\"(\" + queue.size() + \" left on queue)\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ResizingArrayStack.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ResizingArrayStack.java\n *  Execution:    java ResizingArrayStack < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/13stacks/tobe.txt\n *\n *  Stack implementation with a resizing array.\n *\n *  % more tobe.txt\n *  to be or not to - be - - that - - - is\n *\n *  % java ResizingArrayStack < tobe.txt\n *  to be not that or be (2 left on stack)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n/**\n *  The {@code ResizingArrayStack} class represents a last-in-first-out (LIFO) stack\n *  of generic items.\n *  It supports the usual <em>push</em> and <em>pop</em> operations, along with methods\n *  for peeking at the top item, testing if the stack is empty, and iterating through\n *  the items in LIFO order.\n *  <p>\n *  This implementation uses a resizing array, which double the underlying array\n *  when it is full and halves the underlying array when it is one-quarter full.\n *  The <em>push</em> and <em>pop</em> operations take constant amortized time.\n *  The <em>size</em>, <em>peek</em>, and <em>is-empty</em> operations takes\n *  constant time in the worst case.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class ResizingArrayStack<Item> implements Iterable<Item> {\n\n    // initial capacity of underlying resizing array\n    private static final int INIT_CAPACITY = 8;\n\n    private Item[] a;         // array of items\n    private int n;            // number of elements on stack\n\n\n    /**\n     * Initializes an empty stack.\n     */\n    public ResizingArrayStack() {\n        a = (Item[]) new Object[INIT_CAPACITY];\n        n = 0;\n    }\n\n    /**\n     * Is this stack empty?\n     * @return true if this stack is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return n == 0;\n    }\n\n    /**\n     * Returns the number of items in the stack.\n     * @return the number of items in the stack\n     */\n    public int size() {\n        return n;\n    }\n\n\n    // resize the underlying array holding the elements\n    private void resize(int capacity) {\n        assert capacity >= n;\n\n        // textbook implementation\n        Item[] copy = (Item[]) new Object[capacity];\n        for (int i = 0; i < n; i++) {\n            copy[i] = a[i];\n        }\n        a = copy;\n\n       // alternative implementation\n       // a = java.util.Arrays.copyOf(a, capacity);\n    }\n\n\n\n    /**\n     * Adds the item to this stack.\n     * @param item the item to add\n     */\n    public void push(Item item) {\n        if (n == a.length) resize(2*a.length);    // double size of array if necessary\n        a[n++] = item;                            // add item\n    }\n\n    /**\n     * Removes and returns the item most recently added to this stack.\n     * @return the item most recently added\n     * @throws java.util.NoSuchElementException if this stack is empty\n     */\n    public Item pop() {\n        if (isEmpty()) throw new NoSuchElementException(\"Stack underflow\");\n        Item item = a[n-1];\n        a[n-1] = null;                              // to avoid loitering\n        n--;\n        // shrink size of array if necessary\n        if (n > 0 && n == a.length/4) resize(a.length/2);\n        return item;\n    }\n\n\n    /**\n     * Returns (but does not remove) the item most recently added to this stack.\n     * @return the item most recently added to this stack\n     * @throws java.util.NoSuchElementException if this stack is empty\n     */\n    public Item peek() {\n        if (isEmpty()) throw new NoSuchElementException(\"Stack underflow\");\n        return a[n-1];\n    }\n\n    /**\n     * Returns an iterator to this stack that iterates through the items in LIFO order.\n     * @return an iterator to this stack that iterates through the items in LIFO order.\n     */\n    public Iterator<Item> iterator() {\n        return new ReverseArrayIterator();\n    }\n\n    // a array iterator, in reverse order\n    private class ReverseArrayIterator implements Iterator<Item> {\n        private int i;\n\n        public ReverseArrayIterator() {\n            i = n-1;\n        }\n\n        public boolean hasNext() {\n            return i >= 0;\n        }\n\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            return a[i--];\n        }\n    }\n\n\n    /**\n     * Unit tests the {@code Stack} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        ResizingArrayStack<String> stack = new ResizingArrayStack<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\")) stack.push(item);\n            else if (!stack.isEmpty()) StdOut.print(stack.pop() + \" \");\n        }\n        StdOut.println(\"(\" + stack.size() + \" left on stack)\");\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/RunLength.java",
    "content": "/******************************************************************************\n *  Compilation:  javac RunLength.java\n *  Execution:    java RunLength - < input.txt   (compress)\n *  Execution:    java RunLength + < input.txt   (expand)\n *  Dependencies: BinaryIn.java BinaryOut.java\n *  Data files:   https://algs4.cs.princeton.edu/55compression/4runs.bin\n *                https://algs4.cs.princeton.edu/55compression/q32x48.bin\n *                https://algs4.cs.princeton.edu/55compression/q64x96.bin\n *\n *  Compress or expand binary input from standard input using\n *  run-length encoding.\n *\n *  % java BinaryDump 40 < 4runs.bin\n *  0000000000000001111111000000011111111111\n *  40 bits\n *\n *  This has runs of 15 0s, 7 1s, 7 0s, and 11 1s.\n *\n *  % java RunLength - < 4runs.bin | java HexDump\n *  0f 07 07 0b\n *  4 bytes\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code RunLength} class provides static methods for compressing\n *  and expanding a binary input using run-length coding with 8-bit\n *  run lengths.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/55compression\">Section 5.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class RunLength {\n    private static final int R    = 256;\n    private static final int LG_R = 8;\n\n    // Do not instantiate.\n    private RunLength() { }\n\n    /**\n     * Reads a sequence of bits from standard input (that are encoded\n     * using run-length encoding with 8-bit run lengths); decodes them;\n     * and writes the results to standard output.\n     */\n    public static void expand() {\n        boolean b = false;\n        while (!BinaryStdIn.isEmpty()) {\n            int run = BinaryStdIn.readInt(LG_R);\n            for (int i = 0; i < run; i++)\n                BinaryStdOut.write(b);\n            b = !b;\n        }\n        BinaryStdOut.close();\n    }\n\n    /**\n     * Reads a sequence of bits from standard input; compresses\n     * them using run-length coding with 8-bit run lengths; and writes the\n     * results to standard output.\n     */\n    public static void compress() {\n        char run = 0;\n        boolean old = false;\n        while (!BinaryStdIn.isEmpty()) {\n            boolean b = BinaryStdIn.readBoolean();\n            if (b != old) {\n                BinaryStdOut.write(run, LG_R);\n                run = 1;\n                old = !old;\n            }\n            else {\n                if (run == R-1) {\n                    BinaryStdOut.write(run, LG_R);\n                    run = 0;\n                    BinaryStdOut.write(run, LG_R);\n                }\n                run++;\n            }\n        }\n        BinaryStdOut.write(run, LG_R);\n        BinaryStdOut.close();\n    }\n\n\n    /**\n     * Sample client that calls {@code compress()} if the command-line\n     * argument is \"-\" an {@code expand()} if it is \"+\".\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        if      (args[0].equals(\"-\")) compress();\n        else if (args[0].equals(\"+\")) expand();\n        else throw new IllegalArgumentException(\"Illegal command line argument\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SET.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SET.java\n *  Execution:    java SET\n *  Dependencies: StdOut.java\n *\n *  Set implementation using Java's TreeSet library.\n *  Does not allow duplicates.\n *\n *  % java SET\n *  128.112.136.11\n *  208.216.181.15\n *  null\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\nimport java.util.TreeSet;\n\n/**\n *  The {@code SET} class represents an ordered set of comparable keys.\n *  It supports the usual <em>add</em>, <em>contains</em>, and <em>delete</em>\n *  methods. It also provides ordered methods for finding the <em>minimum</em>,\n *  <em>maximum</em>, <em>floor</em>, and <em>ceiling</em> and set methods\n *  for <em>union</em>, <em>intersection</em>, and <em>equality</em>.\n *  <p>\n *  Even though this implementation include the method {@code equals()}, it\n *  does not support the method {@code hashCode()} because sets are mutable.\n *  <p>\n *  This implementation uses a balanced binary search tree. It requires that\n *  the key type implements the {@code Comparable} interface and calls the\n *  {@code compareTo()} and method to compare two keys. It does not call either\n *  {@code equals()} or {@code hashCode()}.\n *  The <em>add</em>, <em>contains</em>, <em>delete</em>, <em>minimum</em>,\n *  <em>maximum</em>, <em>ceiling</em>, and <em>floor</em> methods take\n *  logarithmic time in the worst case.\n *  The <em>size</em>, and <em>is-empty</em> operations take constant time.\n *  Construction takes constant time.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms in Java, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Key> the generic type of each key in this set\n */\n\npublic class SET<Key extends Comparable<Key>> implements Iterable<Key> {\n    private TreeSet<Key> set;\n\n    /**\n     * Initializes an empty set.\n     */\n    public SET() {\n        set = new TreeSet<Key>();\n    }\n\n    /**\n     * Initializes a new set that is an independent copy of the specified set.\n     *\n     * @param x the set to copy\n     */\n    public SET(SET<Key> x) {\n        set = new TreeSet<Key>(x.set);\n    }\n\n    /**\n     * Adds the key to this set (if it is not already present).\n     *\n     * @param  key the key to add\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void add(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"called add() with a null key\");\n        set.add(key);\n    }\n\n\n    /**\n     * Returns true if this set contains the given key.\n     *\n     * @param  key the key\n     * @return {@code true} if this set contains {@code key};\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"called contains() with a null key\");\n        return set.contains(key);\n    }\n\n    /**\n     * Removes the specified key from this set (if the set contains the specified key).\n     * This is equivalent to {@code remove()}, but we plan to deprecate {@code delete()}.\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"called delete() with a null key\");\n        set.remove(key);\n    }\n\n    /**\n     * Removes the specified key from this set (if the set contains the specified key).\n     * This is equivalent to {@code delete()}, but we plan to deprecate {@code delete()}.\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void remove(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"called remove() with a null key\");\n        set.remove(key);\n    }\n\n    /**\n     * Returns the number of keys in this set.\n     *\n     * @return the number of keys in this set\n     */\n    public int size() {\n        return set.size();\n    }\n\n    /**\n     * Returns true if this set is empty.\n     *\n     * @return {@code true} if this set is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns all of the keys in this set, as an iterator.\n     * To iterate over all of the keys in a set named {@code set}, use the\n     * foreach notation: {@code for (Key key : set)}.\n     *\n     * @return an iterator to all of the keys in this set\n     */\n    public Iterator<Key> iterator() {\n        return set.iterator();\n    }\n\n    /**\n     * Returns the largest key in this set.\n     *\n     * @return the largest key in this set\n     * @throws NoSuchElementException if this set is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"called max() with empty set\");\n        return set.last();\n    }\n\n    /**\n     * Returns the smallest key in this set.\n     *\n     * @return the smallest key in this set\n     * @throws NoSuchElementException if this set is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"called min() with empty set\");\n        return set.first();\n    }\n\n\n    /**\n     * Returns the smallest key in this set greater than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the smallest key in this set greater than or equal to {@code key}\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws NoSuchElementException if there is no such key\n     */\n    public Key ceiling(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"called ceiling() with a null key\");\n        Key k = set.ceiling(key);\n        if (k == null) throw new NoSuchElementException(\"all keys are less than \" + key);\n        return k;\n    }\n\n    /**\n     * Returns the largest key in this set less than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the largest key in this set table less than or equal to {@code key}\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     * @throws NoSuchElementException if there is no such key\n     */\n    public Key floor(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"called floor() with a null key\");\n        Key k = set.floor(key);\n        if (k == null) throw new NoSuchElementException(\"all keys are greater than \" + key);\n        return k;\n    }\n\n    /**\n     * Returns the union of this set and that set.\n     *\n     * @param  that the other set\n     * @return the union of this set and that set\n     * @throws IllegalArgumentException if {@code that} is {@code null}\n     */\n    public SET<Key> union(SET<Key> that) {\n        if (that == null) throw new IllegalArgumentException(\"called union() with a null argument\");\n        SET<Key> c = new SET<Key>();\n        for (Key x : this) {\n            c.add(x);\n        }\n        for (Key x : that) {\n            c.add(x);\n        }\n        return c;\n    }\n\n    /**\n     * Returns the intersection of this set and that set.\n     *\n     * @param  that the other set\n     * @return the intersection of this set and that set\n     * @throws IllegalArgumentException if {@code that} is {@code null}\n     */\n    public SET<Key> intersects(SET<Key> that) {\n        if (that == null) throw new IllegalArgumentException(\"called intersects() with a null argument\");\n        SET<Key> c = new SET<Key>();\n        if (this.size() < that.size()) {\n            for (Key x : this) {\n                if (that.contains(x)) c.add(x);\n            }\n        }\n        else {\n            for (Key x : that) {\n                if (this.contains(x)) c.add(x);\n            }\n        }\n        return c;\n    }\n\n    /**\n     * Compares this set to the specified set.\n     * <p>\n     * Note that this method declares two empty sets to be equal\n     * even if they are parameterized by different generic types.\n     * This is consistent with the behavior of {@code equals()}\n     * within Java's Collections framework.\n     *\n     * @param  other the other set\n     * @return {@code true} if this set equals {@code other};\n     *         {@code false} otherwise\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        SET that = (SET) other;\n        return this.set.equals(that.set);\n    }\n\n    /**\n     * This operation is not supported because sets are mutable.\n     *\n     * @return does not return a value\n     * @throws UnsupportedOperationException if called\n     */\n    @Override\n    public int hashCode() {\n        throw new UnsupportedOperationException(\"hashCode() is not supported because sets are mutable\");\n    }\n\n    /**\n     * Returns a string representation of this set.\n     *\n     * @return a string representation of this set, enclosed in curly braces,\n     *         with adjacent keys separated by a comma and a space\n     */\n    @Override\n    public String toString() {\n        String s = set.toString();\n        return \"{ \" + s.substring(1, s.length() - 1) + \" }\";\n    }\n\n    /**\n     * Unit tests the {@code SET} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        SET<String> set = new SET<String>();\n        StdOut.println(\"set = \" + set);\n\n        // insert some keys\n        set.add(\"www.cs.princeton.edu\");\n        set.add(\"www.cs.princeton.edu\");    // overwrite old value\n        set.add(\"www.princeton.edu\");\n        set.add(\"www.math.princeton.edu\");\n        set.add(\"www.yale.edu\");\n        set.add(\"www.amazon.com\");\n        set.add(\"www.simpsons.com\");\n        set.add(\"www.stanford.edu\");\n        set.add(\"www.google.com\");\n        set.add(\"www.ibm.com\");\n        set.add(\"www.apple.com\");\n        set.add(\"www.slashdot.com\");\n        set.add(\"www.whitehouse.gov\");\n        set.add(\"www.espn.com\");\n        set.add(\"www.snopes.com\");\n        set.add(\"www.movies.com\");\n        set.add(\"www.cnn.com\");\n        set.add(\"www.iitb.ac.in\");\n\n\n        StdOut.println(set.contains(\"www.cs.princeton.edu\"));\n        StdOut.println(!set.contains(\"www.harvardsucks.com\"));\n        StdOut.println(set.contains(\"www.simpsons.com\"));\n        StdOut.println();\n\n        StdOut.println(\"ceiling(www.simpsonr.com) = \" + set.ceiling(\"www.simpsonr.com\"));\n        StdOut.println(\"ceiling(www.simpsons.com) = \" + set.ceiling(\"www.simpsons.com\"));\n        StdOut.println(\"ceiling(www.simpsont.com) = \" + set.ceiling(\"www.simpsont.com\"));\n        StdOut.println(\"floor(www.simpsonr.com)   = \" + set.floor(\"www.simpsonr.com\"));\n        StdOut.println(\"floor(www.simpsons.com)   = \" + set.floor(\"www.simpsons.com\"));\n        StdOut.println(\"floor(www.simpsont.com)   = \" + set.floor(\"www.simpsont.com\"));\n        StdOut.println();\n\n        StdOut.println(\"set = \" + set);\n        StdOut.println();\n\n        // print out all keys in this set in lexicographic order\n        for (String s : set) {\n            StdOut.println(s);\n        }\n\n        StdOut.println();\n        SET<String> set2 = new SET<String>(set);\n        StdOut.println(set.equals(set2));\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ST.java\n *  Execution:    java ST < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/35applications/tinyST.txt\n *\n *  Sorted symbol table implementation using a java.util.TreeMap.\n *  Does not allow duplicates.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\nimport java.util.TreeMap;\n\n/**\n *  The {@code ST} class represents an ordered symbol table of generic\n *  key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides ordered methods for finding the <em>minimum</em>,\n *  <em>maximum</em>, <em>floor</em>, and <em>ceiling</em>.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  It requires that\n *  the key type implements the {@code Comparable} interface and calls the\n *  {@code compareTo()} and method to compare two keys. It does not call either\n *  {@code equals()} or {@code hashCode()}.\n *  <p>\n *  This implementation uses a <em>red-black BST</em>.\n *  The <em>put</em>, <em>get</em>, <em>contains</em>, <em>remove</em>,\n *  <em>minimum</em>, <em>maximum</em>, <em>ceiling</em>, and <em>floor</em>\n *  operations each take &Theta;(log <em>n</em>) time in the worst case,\n *  where <em>n</em> is the number of key-value pairs in the symbol table.\n *  The <em>size</em> and <em>is-empty</em> operations take &Theta;(1) time.\n *  Construction takes &Theta;(1) time.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Key> the generic type of keys in this symbol table\n *  @param <Value> the generic type of values in this symbol table\n */\npublic class ST<Key extends Comparable<Key>, Value> implements Iterable<Key> {\n\n    private TreeMap<Key, Value> st;\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public ST() {\n        st = new TreeMap<Key, Value>();\n    }\n\n\n    /**\n     * Returns the value associated with the given key in this symbol table.\n     *\n     * @param  key the key\n     * @return the value associated with the given key if the key is in this symbol table;\n     *         {@code null} if the key is not in this symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"calls get() with null key\");\n        return st.get(key);\n    }\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"calls put() with null key\");\n        if (val == null) st.remove(key);\n        else             st.put(key, val);\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     * This is equivalent to {@code remove()}, but we plan to deprecate {@code delete()}.\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"calls delete() with null key\");\n        st.remove(key);\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     * This is equivalent to {@code delete()}, but we plan to deprecate {@code delete()}.\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void remove(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"calls remove() with null key\");\n        st.remove(key);\n    }\n\n    /**\n     * Returns true if this symbol table contain the given key.\n     *\n     * @param  key the key\n     * @return {@code true} if this symbol table contains {@code key} and\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"calls contains() with null key\");\n        return st.containsKey(key);\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     *\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return st.size();\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     *\n     * @return {@code true} if this symbol table is empty and {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns all keys in this symbol table in ascending order,\n     * as an {@code Iterable}.\n     * <p>\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     *\n     * @return all keys in this symbol table in ascending order\n     */\n    public Iterable<Key> keys() {\n        return st.keySet();\n    }\n\n    /**\n     * Returns all keys in this symbol table in ascending order.\n     * To iterate over all of the keys in a symbol table named {@code st}, use the\n     * foreach notation: {@code for (Key key : st)}.\n     * <p>\n     * This method is provided for backward compatibility with the version from\n     * <em>Introduction to Programming in Java: An Interdisciplinary Approach.</em>\n     *\n     * @return     all keys in this symbol table in ascending order\n     * @deprecated Replaced by {@link #keys()}.\n     */\n    @Deprecated\n    public Iterator<Key> iterator() {\n        return st.keySet().iterator();\n    }\n\n    /**\n     * Returns the smallest key in this symbol table.\n     *\n     * @return the smallest key in this symbol table\n     * @throws NoSuchElementException if this symbol table is empty\n     */\n    public Key min() {\n        if (isEmpty()) throw new NoSuchElementException(\"calls min() with empty symbol table\");\n        return st.firstKey();\n    }\n\n    /**\n     * Returns the largest key in this symbol table.\n     *\n     * @return the largest key in this symbol table\n     * @throws NoSuchElementException if this symbol table is empty\n     */\n    public Key max() {\n        if (isEmpty()) throw new NoSuchElementException(\"calls max() with empty symbol table\");\n        return st.lastKey();\n    }\n\n    /**\n     * Returns the smallest key in this symbol table greater than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the smallest key in this symbol table greater than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key ceiling(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to ceiling() is null\");\n        Key k = st.ceilingKey(key);\n        if (k == null) throw new NoSuchElementException(\"argument to ceiling() is too large\");\n        return k;\n    }\n\n    /**\n     * Returns the largest key in this symbol table less than or equal to {@code key}.\n     *\n     * @param  key the key\n     * @return the largest key in this symbol table less than or equal to {@code key}\n     * @throws NoSuchElementException if there is no such key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Key floor(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to floor() is null\");\n        Key k = st.floorKey(key);\n        if (k == null) throw new NoSuchElementException(\"argument to floor() is too small\");\n        return k;\n    }\n\n    /**\n     * Unit tests the {@code ST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        ST<String, Integer> st = new ST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SegmentTree.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SegmentTree.java\n *  Execution:    java SegmentTree\n *  \n *  A segment tree data structure.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n * The {@code SegmentTree} class is an structure for efficient search of cummulative data.\n * It performs  Range Minimum Query and Range Sum Query in O(log(n)) time.\n * It can be easily customizable to support Range Max Query, Range Multiplication Query etc.\n * <p>\n * Also it has been develop with  {@code LazyPropagation} for range updates, which means\n * when you perform update operations over a range, the update process affects the least nodes as possible\n * so that the bigger the range you want to update the less time it consumes to update it. Eventually those changes will be propagated\n * to the children and the whole array will be up to date.\n * <p>\n * Example:\n * <p>\n * SegmentTreeHeap st = new SegmentTreeHeap(new Integer[]{1,3,4,2,1, -2, 4});\n * st.update(0,3, 1)\n * In the above case only the node that represents the range [0,3] will be updated (and not their children) so in this case\n * the update task will be less than n*log(n)\n *\n * Memory usage:  O(n)\n *\n * @author Ricardo Pacheco \n */\npublic class SegmentTree {\n\n    private Node[] heap;\n    private int[] array;\n    private int size;\n\n    /**\n     * Time-Complexity:  O(n*log(n))\n     *\n     * @param array the Initialization array\n     */\n    public SegmentTree(int[] array) {\n        this.array = Arrays.copyOf(array, array.length);\n        //The max size of this array is about 2 * 2 ^ log2(n) + 1\n        size = (int) (2 * Math.pow(2.0, Math.floor((Math.log((double) array.length) / Math.log(2.0)) + 1)));\n        heap = new Node[size];\n        build(1, 0, array.length);\n    }\n\n\n    public int size() {\n        return array.length;\n    }\n\n    //Initialize the Nodes of the Segment tree\n    private void build(int v, int from, int size) {\n        heap[v] = new Node();\n        heap[v].from = from;\n        heap[v].to = from + size - 1;\n\n        if (size == 1) {\n            heap[v].sum = array[from];\n            heap[v].min = array[from];\n        } else {\n            //Build childs\n            build(2 * v, from, size / 2);\n            build(2 * v + 1, from + size / 2, size - size / 2);\n\n            heap[v].sum = heap[2 * v].sum + heap[2 * v + 1].sum;\n            //min = min of the children\n            heap[v].min = Math.min(heap[2 * v].min, heap[2 * v + 1].min);\n        }\n    }\n\n    /**\n     * Range Sum Query\n     *\n     * Time-Complexity: O(log(n))\n     *\n     * @param  from from index\n     * @param  to to index\n     * @return sum\n     */\n    public int rsq(int from, int to) {\n        return rsq(1, from, to);\n    }\n\n    private int rsq(int v, int from, int to) {\n        Node n = heap[v];\n\n        //If you did a range update that contained this node, you can infer the Sum without going down the tree\n        if (n.pendingVal != null && contains(n.from, n.to, from, to)) {\n            return (to - from + 1) * n.pendingVal;\n        }\n\n        if (contains(from, to, n.from, n.to)) {\n            return heap[v].sum;\n        }\n\n        if (intersects(from, to, n.from, n.to)) {\n            propagate(v);\n            int leftSum = rsq(2 * v, from, to);\n            int rightSum = rsq(2 * v + 1, from, to);\n\n            return leftSum + rightSum;\n        }\n\n        return 0;\n    }\n\n    /**\n     * Range Min Query\n     * \n     * Time-Complexity: O(log(n))\n     *\n     * @param  from from index\n     * @param  to to index\n     * @return min\n     */\n    public int rMinQ(int from, int to) {\n        return rMinQ(1, from, to);\n    }\n\n    private int rMinQ(int v, int from, int to) {\n        Node n = heap[v];\n\n\n        //If you did a range update that contained this node, you can infer the Min value without going down the tree\n        if (n.pendingVal != null && contains(n.from, n.to, from, to)) {\n            return n.pendingVal;\n        }\n\n        if (contains(from, to, n.from, n.to)) {\n            return heap[v].min;\n        }\n\n        if (intersects(from, to, n.from, n.to)) {\n            propagate(v);\n            int leftMin = rMinQ(2 * v, from, to);\n            int rightMin = rMinQ(2 * v + 1, from, to);\n\n            return Math.min(leftMin, rightMin);\n        }\n\n        return Integer.MAX_VALUE;\n    }\n\n\n    /**\n     * Range Update Operation.\n     * With this operation you can update either one position or a range of positions with a given number.\n     * The update operations will update the less it can to update the whole range (Lazy Propagation).\n     * The values will be propagated lazily from top to bottom of the segment tree.\n     * This behavior is really useful for updates on portions of the array\n     * <p>\n     * Time-Complexity: O(log(n))\n     *\n     * @param from  from index\n     * @param to    to index\n     * @param value value\n     */\n    public void update(int from, int to, int value) {\n        update(1, from, to, value);\n    }\n\n    private void update(int v, int from, int to, int value) {\n\n        //The Node of the heap tree represents a range of the array with bounds: [n.from, n.to]\n        Node n = heap[v];\n\n        /**\n         * If the updating-range contains the portion of the current Node  We lazily update it.\n         * This means We do NOT update each position of the vector, but update only some temporal\n         * values into the Node; such values into the Node will be propagated down to its children only when they need to.\n         */\n        if (contains(from, to, n.from, n.to)) {\n            change(n, value);\n        }\n\n        if (n.size() == 1) return;\n\n        if (intersects(from, to, n.from, n.to)) {\n            /**\n             * Before keeping going down to the tree We need to propagate the\n             * the values that have been temporally/lazily saved into this Node to its children\n             * So that when We visit them the values  are properly updated\n             */\n            propagate(v);\n\n            update(2 * v, from, to, value);\n            update(2 * v + 1, from, to, value);\n\n            n.sum = heap[2 * v].sum + heap[2 * v + 1].sum;\n            n.min = Math.min(heap[2 * v].min, heap[2 * v + 1].min);\n        }\n    }\n\n    //Propagate temporal values to children\n    private void propagate(int v) {\n        Node n = heap[v];\n\n        if (n.pendingVal != null) {\n            change(heap[2 * v], n.pendingVal);\n            change(heap[2 * v + 1], n.pendingVal);\n            n.pendingVal = null; //unset the pending propagation value\n        }\n    }\n\n    //Save the temporal values that will be propagated lazily\n    private void change(Node n, int value) {\n        n.pendingVal = value;\n        n.sum = n.size() * value;\n        n.min = value;\n        array[n.from] = value;\n\n    }\n\n    //Test if the range1 contains range2\n    private boolean contains(int from1, int to1, int from2, int to2) {\n        return from2 >= from1 && to2 <= to1;\n    }\n\n    //check inclusive intersection, test if range1[from1, to1] intersects range2[from2, to2]\n    private boolean intersects(int from1, int to1, int from2, int to2) {\n        return from1 <= from2 && to1 >= from2   //  (.[..)..] or (.[...]..)\n                || from1 >= from2 && from1 <= to2; // [.(..]..) or [..(..)..\n    }\n\n    //The Node class represents a partition range of the array.\n    static class Node {\n        int sum;\n        int min;\n        //Here We store the value that will be propagated lazily\n        Integer pendingVal = null;\n        int from;\n        int to;\n\n        int size() {\n            return to - from + 1;\n        }\n\n    }\n\n    /**\n     * Read the following commands:\n     * init n v     Initializes the array of size n with all v's\n     * set a b c... Initializes the array  with [a, b, c ...]\n     * rsq a b      Range Sum Query for the range [a, b]\n     * rmq a b      Range Min Query for the range [a, b]\n     * up  a b v    Update the [a,b] portion of the array with value v.\n     * exit\n     * <p>\n     * Example:\n     * init\n     * set 1 2 3 4 5 6\n     * rsq 1 3\n     * Sum from 1 to 3 = 6\n     * rmq 1 3\n     * Min from 1 to 3 = 1\n     * input up 1 3\n     * [3,2,3,4,5,6]\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n\n        SegmentTree st = null;\n\n        String cmd = \"cmp\";\n        while (true) {\n            String[] line = StdIn.readLine().split(\" \");\n\n            if (line[0].equals(\"exit\")) break;\n\n            int arg1 = 0, arg2 = 0, arg3 = 0;\n\n            if (line.length > 1) {\n                arg1 = Integer.parseInt(line[1]);\n            }\n            if (line.length > 2) {\n                arg2 = Integer.parseInt(line[2]);\n            }\n            if (line.length > 3) {\n                arg3 = Integer.parseInt(line[3]);\n            }\n\n            if ((!line[0].equals(\"set\") && !line[0].equals(\"init\")) && st == null) {\n                StdOut.println(\"Segment Tree not initialized\");\n                continue;\n            }\n            int array[];\n            if (line[0].equals(\"set\")) {\n                array = new int[line.length - 1];\n                for (int i = 0; i < line.length - 1; i++) {\n                    array[i] = Integer.parseInt(line[i + 1]);\n                }\n                st = new SegmentTree(array);\n            }\n            else if (line[0].equals(\"init\")) {\n                array = new int[arg1];\n                Arrays.fill(array, arg2);\n                st = new SegmentTree(array);\n\n                for (int i = 0; i < st.size(); i++) {\n                    StdOut.print(st.rsq(i, i) + \" \");\n                }\n                StdOut.println();\n            }\n\n            else if (line[0].equals(\"up\")) {\n                st.update(arg1, arg2, arg3);\n                for (int i = 0; i < st.size(); i++) {\n                    StdOut.print(st.rsq(i, i) + \" \");\n                }\n                StdOut.println();\n            }\n            else if (line[0].equals(\"rsq\")) {\n                StdOut.printf(\"Sum from %d to %d = %d%n\", arg1, arg2, st.rsq(arg1, arg2));\n            }\n            else if (line[0].equals(\"rmq\")) {\n                StdOut.printf(\"Min from %d to %d = %d%n\", arg1, arg2, st.rMinQ(arg1, arg2));\n            }\n            else {\n                StdOut.println(\"Invalid command\");\n            }\n\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Selection.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Selection.java\n *  Execution:    java  Selection < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/21elementary/tiny.txt\n *                https://algs4.cs.princeton.edu/21elementary/words3.txt\n *\n *  Sorts a sequence of strings from standard input using selection sort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Selection < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Selection < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Comparator;\n\n/**\n *  The {@code Selection} class provides static methods for sorting an\n *  array using <em>selection sort</em>.\n *  This implementation makes ~ &frac12; <em>n</em><sup>2</sup> compares to sort\n *  any array of length <em>n</em>, so it is not suitable for sorting large arrays.\n *  It performs exactly <em>n</em> exchanges.\n *  <p>\n *  This sorting algorithm is not stable. It uses &Theta;(1) extra memory\n *  (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/21elementary\">Section 2.1</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Selection {\n\n    // This class should not be instantiated.\n    private Selection() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            int min = i;\n            for (int j = i+1; j < n; j++) {\n                if (less(a[j], a[min])) min = j;\n            }\n            exch(a, i, min);\n            assert isSorted(a, 0, i);\n        }\n        assert isSorted(a);\n    }\n\n    /**\n     * Rearranges the array in ascending order, using a comparator.\n     * @param a the array\n     * @param comparator the comparator specifying the order\n     */\n    public static void sort(Object[] a, Comparator comparator) {\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            int min = i;\n            for (int j = i+1; j < n; j++) {\n                if (less(comparator, a[j], a[min])) min = j;\n            }\n            exch(a, i, min);\n            assert isSorted(a, comparator, 0, i);\n        }\n        assert isSorted(a, comparator);\n    }\n\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // is v < w ?\n    private static boolean less(Comparator comparator, Object v, Object w) {\n        return comparator.compare(v, w) < 0;\n    }\n\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n\n    // is the array a[] sorted?\n    private static boolean isSorted(Comparable[] a) {\n        return isSorted(a, 0, a.length - 1);\n    }\n\n    // is the array sorted from a[lo] to a[hi]\n    private static boolean isSorted(Comparable[] a, int lo, int hi) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // is the array a[] sorted?\n    private static boolean isSorted(Object[] a, Comparator comparator) {\n        return isSorted(a, comparator, 0, a.length - 1);\n    }\n\n    // is the array sorted from a[lo] to a[hi]\n    private static boolean isSorted(Object[] a, Comparator comparator, int lo, int hi) {\n        for (int i = lo + 1; i <= hi; i++)\n            if (less(comparator, a[i], a[i-1])) return false;\n        return true;\n    }\n\n\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; selection sorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Selection.sort(a);\n        show(a);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SeparateChainingHashST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SeparateChainingHashST.java\n *  Execution:    java SeparateChainingHashST < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/34hash/tinyST.txt\n *\n *  A symbol table implemented with a separate-chaining hash table.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code SeparateChainingHashST} class represents a symbol table of generic\n *  key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  This implementation uses a separate chaining hash table. It requires that\n *  the key type overrides the {@code equals()} and {@code hashCode()} methods.\n *  The expected time per <em>put</em>, <em>contains</em>, or <em>remove</em>\n *  operation is constant, subject to the uniform hashing assumption.\n *  The <em>size</em>, and <em>is-empty</em> operations take constant time.\n *  Construction takes constant time.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/34hash\">Section 3.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  For other implementations, see {@link ST}, {@link BinarySearchST},\n *  {@link SequentialSearchST}, {@link BST}, {@link RedBlackBST}, and\n *  {@link LinearProbingHashST},\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class SeparateChainingHashST<Key, Value> {\n    private static final int INIT_CAPACITY = 4;\n\n    private int n;                                // number of key-value pairs\n    private int m;                                // hash table size\n    private SequentialSearchST<Key, Value>[] st;  // array of linked-list symbol tables\n\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public SeparateChainingHashST() {\n        this(INIT_CAPACITY);\n    }\n\n    /**\n     * Initializes an empty symbol table with {@code m} chains.\n     * @param m the initial number of chains\n     */\n    public SeparateChainingHashST(int m) {\n        this.m = m;\n        st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[m];\n        for (int i = 0; i < m; i++)\n            st[i] = new SequentialSearchST<Key, Value>();\n    }\n\n    // resize the hash table to have the given number of chains,\n    // rehashing all of the keys\n    private void resize(int chains) {\n        SeparateChainingHashST<Key, Value> temp = new SeparateChainingHashST<Key, Value>(chains);\n        for (int i = 0; i < m; i++) {\n            for (Key key : st[i].keys()) {\n                temp.put(key, st[i].get(key));\n            }\n        }\n        this.m  = temp.m;\n        this.n  = temp.n;\n        this.st = temp.st;\n    }\n\n    // hash function for keys - returns value between 0 and m-1\n    private int hashTextbook(Key key) {\n        return (key.hashCode() & 0x7fffffff) % m;\n    }\n\n    // hash function for keys - returns value between 0 and m-1 (assumes m is a power of 2)\n    // (from Java 7 implementation, protects against poor quality hashCode() implementations)\n    private int hash(Key key) {\n        int h = key.hashCode();\n        h ^= (h >>> 20) ^ (h >>> 12) ^ (h >>> 7) ^ (h >>> 4);\n        return h & (m-1);\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     *\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     *\n     * @return {@code true} if this symbol table is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns true if this symbol table contains the specified key.\n     *\n     * @param  key the key\n     * @return {@code true} if this symbol table contains {@code key};\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        return get(key) != null;\n    }\n\n    /**\n     * Returns the value associated with the specified key in this symbol table.\n     *\n     * @param  key the key\n     * @return the value associated with {@code key} in the symbol table;\n     *         {@code null} if no such value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        int i = hash(key);\n        return st[i].get(key);\n    }\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n        if (val == null) {\n            delete(key);\n            return;\n        }\n\n        // double table size if average length of list >= 10\n        if (n >= 10*m) resize(2*m);\n\n        int i = hash(key);\n        if (!st[i].contains(key)) n++;\n        st[i].put(key, val);\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n\n        int i = hash(key);\n        if (st[i].contains(key)) n--;\n        st[i].delete(key);\n\n        // halve table size if average length of list <= 2\n        if (m > INIT_CAPACITY && n <= 2*m) resize(m/2);\n    }\n\n    // return keys in symbol table as an Iterable\n    public Iterable<Key> keys() {\n        Queue<Key> queue = new Queue<Key>();\n        for (int i = 0; i < m; i++) {\n            for (Key key : st[i].keys())\n                queue.enqueue(key);\n        }\n        return queue;\n    }\n\n\n    /**\n     * Unit tests the {@code SeparateChainingHashST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n\n        // print keys\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SequentialSearchST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SequentialSearchST.java\n *  Execution:    java SequentialSearchST\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/31elementary/tinyST.txt\n *\n *  Symbol table implementation with sequential search in an\n *  unordered linked list of key-value pairs.\n *\n *  % more tinyST.txt\n *  S E A R C H E X A M P L E\n *\n *  % java SequentialSearchST < tinyST.txt\n *  L 11\n *  P 10\n *  M 9\n *  X 7\n *  H 5\n *  C 4\n *  R 3\n *  A 8\n *  E 12\n *  S 0\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code SequentialSearchST} class represents an (unordered)\n *  symbol table of generic key-value pairs.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides a <em>keys</em> method for iterating over all of the keys.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  The class also uses the convention that values cannot be {@code null}. Setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  It relies on the {@code equals()} method to test whether two keys\n *  are equal. It does not call either the {@code compareTo()} or\n *  {@code hashCode()} method.\n *  <p>\n *  This implementation uses a <em>singly linked list</em> and\n *  <em>sequential search</em>.\n *  The <em>put</em> and <em>delete</em> operations take &Theta;(<em>n</em>).\n *  The <em>get</em> and <em>contains</em> operations takes &Theta;(<em>n</em>)\n *  time in the worst case.\n *  The <em>size</em>, and <em>is-empty</em> operations take &Theta;(1) time.\n *  Construction takes &Theta;(1) time.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/31elementary\">Section 3.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class SequentialSearchST<Key, Value> {\n    private int n;           // number of key-value pairs\n    private Node first;      // the linked list of key-value pairs\n\n    // a helper linked list data type\n    private class Node {\n        private Key key;\n        private Value val;\n        private Node next;\n\n        public Node(Key key, Value val, Node next)  {\n            this.key  = key;\n            this.val  = val;\n            this.next = next;\n        }\n    }\n\n    /**\n     * Initializes an empty symbol table.\n     */\n    public SequentialSearchST() {\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     *\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Returns true if this symbol table is empty.\n     *\n     * @return {@code true} if this symbol table is empty;\n     *         {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns true if this symbol table contains the specified key.\n     *\n     * @param  key the key\n     * @return {@code true} if this symbol table contains {@code key};\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        return get(key) != null;\n    }\n\n    /**\n     * Returns the value associated with the given key in this symbol table.\n     *\n     * @param  key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *     and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        for (Node x = first; x != null; x = x.next) {\n            if (key.equals(x.key))\n                return x.val;\n        }\n        return null;\n    }\n\n    /**\n     * Inserts the specified key-value pair into the symbol table, overwriting the old\n     * value with the new value if the symbol table already contains the specified key.\n     * Deletes the specified key (and its associated value) from this symbol table\n     * if the specified value is {@code null}.\n     *\n     * @param  key the key\n     * @param  val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(Key key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n        if (val == null) {\n            delete(key);\n            return;\n        }\n\n        for (Node x = first; x != null; x = x.next) {\n            if (key.equals(x.key)) {\n                x.val = val;\n                return;\n            }\n        }\n        first = new Node(key, val, first);\n        n++;\n    }\n\n    /**\n     * Removes the specified key and its associated value from this symbol table\n     * (if the key is in this symbol table).\n     *\n     * @param  key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(Key key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        first = delete(first, key);\n    }\n\n    // delete key in linked list beginning at Node x\n    // warning: function call stack too large if table is large\n    private Node delete(Node x, Key key) {\n        if (x == null) return null;\n        if (key.equals(x.key)) {\n            n--;\n            return x.next;\n        }\n        x.next = delete(x.next, key);\n        return x;\n    }\n\n\n    /**\n     * Returns all keys in the symbol table as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     *\n     * @return all keys in the symbol table\n     */\n    public Iterable<Key> keys()  {\n        Queue<Key> queue = new Queue<Key>();\n        for (Node x = first; x != null; x = x.next)\n            queue.enqueue(x.key);\n        return queue;\n    }\n\n\n    /**\n     * Unit tests the {@code SequentialSearchST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        SequentialSearchST<String, Integer> st = new SequentialSearchST<String, Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n        for (String s : st.keys())\n            StdOut.println(s + \" \" + st.get(s));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Shell.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Shell.java\n *  Execution:    java Shell < input.txt\n *  Dependencies: StdOut.java StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/21elementary/tiny.txt\n *                https://algs4.cs.princeton.edu/21elementary/words3.txt\n *\n *  Sorts a sequence of strings from standard input using shellsort.\n *\n *  % more tiny.txt\n *  S O R T E X A M P L E\n *\n *  % java Shell < tiny.txt\n *  A E E L M O P R S T X                 [ one string per line ]\n *\n *  % more words3.txt\n *  bed bug dad yes zoo ... all bad yet\n *\n *  % java Shell < words3.txt\n *  all bad bed bug dad ... yes yet zoo    [ one string per line ]\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Shell} class provides static methods for sorting an\n *  array using <em>Shellsort</em> with\n *  <a href = \"https://oeis.org/A003462\"> Knuth's increment sequence</a>\n *  (1, 4, 13, 40, ...). In the worst case, this implementation makes\n *  &Theta;(<em>n</em><sup>3/2</sup>) compares and exchanges to sort\n *  an array of length <em>n</em>.\n *  <p>\n *  This sorting algorithm is not stable.\n *  It uses &Theta;(1) extra memory (not including the input array).\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/21elementary\">Section 2.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Shell {\n\n    // This class should not be instantiated.\n    private Shell() { }\n\n    /**\n     * Rearranges the array in ascending order, using the natural order.\n     * @param a the array to be sorted\n     */\n    public static void sort(Comparable[] a) {\n        int n = a.length;\n\n        // 3x+1 increment sequence:  1, 4, 13, 40, 121, 364, 1093, ...\n        int h = 1;\n        while (h < n/3) h = 3*h + 1;\n\n        while (h >= 1) {\n            // h-sort the array\n            for (int i = h; i < n; i++) {\n                for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {\n                    exch(a, j, j-h);\n                }\n            }\n            assert isHsorted(a, h);\n            h /= 3;\n        }\n        assert isSorted(a);\n    }\n\n\n\n   /***************************************************************************\n    *  Helper sorting functions.\n    ***************************************************************************/\n\n    // is v < w ?\n    private static boolean less(Comparable v, Comparable w) {\n        return v.compareTo(w) < 0;\n    }\n\n    // exchange a[i] and a[j]\n    private static void exch(Object[] a, int i, int j) {\n        Object swap = a[i];\n        a[i] = a[j];\n        a[j] = swap;\n    }\n\n\n   /***************************************************************************\n    *  Check if array is sorted - useful for debugging.\n    ***************************************************************************/\n    private static boolean isSorted(Comparable[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (less(a[i], a[i-1])) return false;\n        return true;\n    }\n\n    // is the array h-sorted?\n    private static boolean isHsorted(Comparable[] a, int h) {\n        for (int i = h; i < a.length; i++)\n            if (less(a[i], a[i-h])) return false;\n        return true;\n    }\n\n    // print array to standard output\n    private static void show(Comparable[] a) {\n        for (int i = 0; i < a.length; i++) {\n            StdOut.println(a[i]);\n        }\n    }\n\n    /**\n     * Reads in a sequence of strings from standard input; Shellsorts them;\n     * and prints them to standard output in ascending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String[] a = StdIn.readAllStrings();\n        Shell.sort(a);\n        show(a);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SparseVector.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SparseVector.java\n *  Execution:    java SparseVector\n *  Dependencies: StdOut.java\n *\n *  A sparse vector, implementing using a symbol table.\n *\n *  [Not clear we need the instance variable N except for error checking.]\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code SparseVector} class represents a <em>d</em>-dimensional mathematical vector.\n *  Vectors are mutable: their values can be changed after they are created.\n *  It includes methods for addition, subtraction,\n *  dot product, scalar product, unit vector, and Euclidean norm.\n *  <p>\n *  The implementation is a symbol table of indices and values for which the vector\n *  coordinates are nonzero. This makes it efficient when most of the vector coordinates\n  * are zero.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/35applications\">Section 3.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *  See also {@link Vector} for an immutable (dense) vector data type.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class SparseVector {\n    private int d;                   // dimension\n    private ST<Integer, Double> st;  // the vector, represented by index-value pairs\n\n   /**\n     * Initializes a d-dimensional zero vector.\n     * @param d the dimension of the vector\n     */\n    public SparseVector(int d) {\n        this.d  = d;\n        this.st = new ST<Integer, Double>();\n    }\n\n   /**\n     * Sets the ith coordinate of this vector to the specified value.\n     *\n     * @param  i the index\n     * @param  value the new value\n     * @throws IllegalArgumentException unless i is between 0 and d-1\n     */\n    public void put(int i, double value) {\n        if (i < 0 || i >= d) throw new IllegalArgumentException(\"Illegal index\");\n        if (value == 0.0) st.delete(i);\n        else              st.put(i, value);\n    }\n\n   /**\n     * Returns the ith coordinate of this vector.\n     *\n     * @param  i the index\n     * @return the value of the ith coordinate of this vector\n     * @throws IllegalArgumentException unless i is between 0 and d-1\n     */\n    public double get(int i) {\n        if (i < 0 || i >= d) throw new IllegalArgumentException(\"Illegal index\");\n        if (st.contains(i)) return st.get(i);\n        else                return 0.0;\n    }\n\n   /**\n     * Returns the number of nonzero entries in this vector.\n     *\n     * @return the number of nonzero entries in this vector\n     */\n    public int nnz() {\n        return st.size();\n    }\n\n   /**\n     * Returns the dimension of this vector.\n     *\n     * @return the dimension of this vector\n     * @deprecated Replaced by {@link #dimension()}.\n     */\n    @Deprecated\n    public int size() {\n        return d;\n    }\n\n   /**\n     * Returns the dimension of this vector.\n     *\n     * @return the dimension of this vector\n     */\n    public int dimension() {\n        return d;\n    }\n\n    /**\n     * Returns the inner product of this vector with the specified vector.\n     *\n     * @param  that the other vector\n     * @return the dot product between this vector and that vector\n     * @throws IllegalArgumentException if the lengths of the two vectors are not equal\n     */\n    public double dot(SparseVector that) {\n        if (this.d != that.d) throw new IllegalArgumentException(\"Vector lengths disagree\");\n        double sum = 0.0;\n\n        // iterate over the vector with the fewest nonzeros\n        if (this.st.size() <= that.st.size()) {\n            for (int i : this.st.keys())\n                if (that.st.contains(i)) sum += this.get(i) * that.get(i);\n        }\n        else  {\n            for (int i : that.st.keys())\n                if (this.st.contains(i)) sum += this.get(i) * that.get(i);\n        }\n        return sum;\n    }\n\n\n    /**\n     * Returns the inner product of this vector with the specified array.\n     *\n     * @param  that the array\n     * @return the dot product between this vector and that array\n     * @throws IllegalArgumentException if the dimensions of the vector and the array are not equal\n     */\n    public double dot(double[] that) {\n        double sum = 0.0;\n        for (int i : st.keys())\n            sum += that[i] * this.get(i);\n        return sum;\n    }\n\n    /**\n     * Returns the magnitude of this vector.\n     * This is also known as the L2 norm or the Euclidean norm.\n     *\n     * @return the magnitude of this vector\n     */\n    public double magnitude() {\n        return Math.sqrt(this.dot(this));\n    }\n\n\n    /**\n     * Returns the Euclidean norm of this vector.\n     *\n     * @return the Euclidean norm of this vector\n     * @deprecated Replaced by {@link #magnitude()}.\n     */\n    @Deprecated\n    public double norm() {\n        return Math.sqrt(this.dot(this));\n    }\n\n    /**\n     * Returns the scalar-vector product of this vector with the specified scalar.\n     *\n     * @param  alpha the scalar\n     * @return the scalar-vector product of this vector with the specified scalar\n     */\n    public SparseVector scale(double alpha) {\n        SparseVector c = new SparseVector(d);\n        for (int i : this.st.keys()) c.put(i, alpha * this.get(i));\n        return c;\n    }\n\n    /**\n     * Returns the sum of this vector and the specified vector.\n     *\n     * @param  that the vector to add to this vector\n     * @return the sum of this vector and that vector\n     * @throws IllegalArgumentException if the dimensions of the two vectors are not equal\n     */\n    public SparseVector plus(SparseVector that) {\n        if (this.d != that.d) throw new IllegalArgumentException(\"Vector lengths disagree\");\n        SparseVector c = new SparseVector(d);\n        for (int i : this.st.keys()) c.put(i, this.get(i));                // c = this\n        for (int i : that.st.keys()) c.put(i, that.get(i) + c.get(i));     // c = c + that\n        return c;\n    }\n\n   /**\n     * Returns a string representation of this vector.\n     * @return a string representation of this vector, which consists of the\n     *         vector entries, separates by commas, enclosed in parentheses\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (int i : st.keys()) {\n            s.append(\"(\" + i + \", \" + st.get(i) + \") \");\n        }\n        return s.toString();\n    }\n\n\n    /**\n     * Unit tests the {@code SparseVector} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        SparseVector a = new SparseVector(10);\n        SparseVector b = new SparseVector(10);\n        a.put(3, 0.50);\n        a.put(9, 0.75);\n        a.put(6, 0.11);\n        a.put(6, 0.00);\n        b.put(3, 0.60);\n        b.put(4, 0.90);\n        StdOut.println(\"a = \" + a);\n        StdOut.println(\"b = \" + b);\n        StdOut.println(\"a dot b = \" + a.dot(b));\n        StdOut.println(\"a + b   = \" + a.plus(b));\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Stack.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Stack.java\n *  Execution:    java Stack < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/13stacks/tobe.txt\n *\n *  A generic stack, implemented using a singly linked list.\n *  Each stack element is of type Item.\n *\n *  This version uses a static nested class Node (to save 8 bytes per\n *  Node), whereas the version in the textbook uses a non-static nested\n *  class (for simplicity).\n *\n *  % more tobe.txt\n *  to be or not to - be - - that - - - is\n *\n *  % java Stack < tobe.txt\n *  to be not that or be (2 left on stack)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\nimport java.util.NoSuchElementException;\n\n\n/**\n *  The {@code Stack} class represents a last-in-first-out (LIFO) stack of generic items.\n *  It supports the usual <em>push</em> and <em>pop</em> operations, along with methods\n *  for peeking at the top item, testing if the stack is empty, and iterating through\n *  the items in LIFO order.\n *  <p>\n *  This implementation uses a singly linked list with a static nested class for\n *  linked-list nodes. See {@link LinkedStack} for the version from the\n *  textbook that uses a non-static nested class.\n *  See {@link ResizingArrayStack} for a version that uses a resizing array.\n *  The <em>push</em>, <em>pop</em>, <em>peek</em>, <em>size</em>, and <em>is-empty</em>\n *  operations all take constant time in the worst case.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/13stacks\">Section 1.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *\n *  @param <Item> the generic type each item in this stack\n */\npublic class Stack<Item> implements Iterable<Item> {\n    private Node<Item> first;     // top of stack\n    private int n;                // size of the stack\n\n    // helper linked list class\n    private static class Node<Item> {\n        private Item item;\n        private Node<Item> next;\n    }\n\n    /**\n     * Initializes an empty stack.\n     */\n    public Stack() {\n        first = null;\n        n = 0;\n    }\n\n    /**\n     * Returns true if this stack is empty.\n     *\n     * @return true if this stack is empty; false otherwise\n     */\n    public boolean isEmpty() {\n        return first == null;\n    }\n\n    /**\n     * Returns the number of items in this stack.\n     *\n     * @return the number of items in this stack\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Adds the item to this stack.\n     *\n     * @param  item the item to add\n     */\n    public void push(Item item) {\n        Node<Item> oldfirst = first;\n        first = new Node<Item>();\n        first.item = item;\n        first.next = oldfirst;\n        n++;\n    }\n\n    /**\n     * Removes and returns the item most recently added to this stack.\n     *\n     * @return the item most recently added\n     * @throws NoSuchElementException if this stack is empty\n     */\n    public Item pop() {\n        if (isEmpty()) throw new NoSuchElementException(\"Stack underflow\");\n        Item item = first.item;        // save item to return\n        first = first.next;            // delete first node\n        n--;\n        return item;                   // return the saved item\n    }\n\n\n    /**\n     * Returns (but does not remove) the item most recently added to this stack.\n     *\n     * @return the item most recently added to this stack\n     * @throws NoSuchElementException if this stack is empty\n     */\n    public Item peek() {\n        if (isEmpty()) throw new NoSuchElementException(\"Stack underflow\");\n        return first.item;\n    }\n\n    /**\n     * Returns a string representation of this stack.\n     *\n     * @return the sequence of items in this stack in LIFO order, separated by spaces\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (Item item : this) {\n            s.append(item);\n            s.append(' ');\n        }\n        return s.toString();\n    }\n\n\n    /**\n     * Returns an iterator to this stack that iterates through the items in LIFO order.\n     *\n     * @return an iterator to this stack that iterates through the items in LIFO order\n     */\n    public Iterator<Item> iterator() {\n        return new LinkedIterator(first);\n    }\n\n    // the iterator\n    private class LinkedIterator implements Iterator<Item> {\n        private Node<Item> current;\n\n        public LinkedIterator(Node<Item> first) {\n            current = first;\n        }\n\n        // is there a next item?\n        public boolean hasNext() {\n            return current != null;\n        }\n\n        // returns the next item\n        public Item next() {\n            if (!hasNext()) throw new NoSuchElementException();\n            Item item = current.item;\n            current = current.next;\n            return item;\n        }\n    }\n\n\n    /**\n     * Unit tests the {@code Stack} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Stack<String> stack = new Stack<String>();\n        while (!StdIn.isEmpty()) {\n            String item = StdIn.readString();\n            if (!item.equals(\"-\"))\n                stack.push(item);\n            else if (!stack.isEmpty())\n                StdOut.print(stack.pop() + \" \");\n        }\n        StdOut.println(\"(\" + stack.size() + \" left on stack)\");\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StaticSETofInts.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StaticSetOfInts.java\n *  Execution:    none\n *  Dependencies: StdOut.java\n *\n *  Data type to store a set of integers.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n *  The {@code StaticSETofInts} class represents a set of integers.\n *  It supports searching for a given integer is in the set. It accomplishes\n *  this by keeping the set of integers in a sorted array and using\n *  binary search to find the given integer.\n *  <p>\n *  The <em>rank</em> and <em>contains</em> operations take\n *  logarithmic time in the worst case.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class StaticSETofInts {\n    private int[] a;\n\n    /**\n     * Initializes a set of integers specified by the integer array.\n     * @param keys the array of integers\n     * @throws IllegalArgumentException if the array contains duplicate integers\n     */\n    public StaticSETofInts(int[] keys) {\n\n        // defensive copy\n        a = new int[keys.length];\n        for (int i = 0; i < keys.length; i++)\n            a[i] = keys[i];\n\n        // sort the integers\n        Arrays.sort(a);\n\n        // check for duplicates\n        for (int i = 1; i < a.length; i++)\n            if (a[i] == a[i-1])\n                throw new IllegalArgumentException(\"Argument arrays contains duplicate keys.\");\n    }\n\n    /**\n     * Is the key in this set of integers?\n     * @param key the search key\n     * @return true if the set of integers contains the key; false otherwise\n     */\n    public boolean contains(int key) {\n        return rank(key) != -1;\n    }\n\n    /**\n     * Returns either the index of the search key in the sorted array\n     * (if the key is in the set) or -1 (if the key is not in the set).\n     * @param key the search key\n     * @return the number of keys in this set less than the key (if the key is in the set)\n     * or -1 (if the key is not in the set).\n     */\n    public int rank(int key) {\n        int lo = 0;\n        int hi = a.length - 1;\n        while (lo <= hi) {\n            // Key is in a[lo..hi] or not present.\n            int mid = lo + (hi - lo) / 2;\n            if      (key < a[mid]) hi = mid - 1;\n            else if (key > a[mid]) lo = mid + 1;\n            else return mid;\n        }\n        return -1;\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdArrayIO.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdArrayIO.java\n *  Execution:    java StdArrayIO < input.txt\n *  Dependencies: StdOut.java\n *  Data files:    https://introcs.cs.princeton.edu/java/22library/tinyDouble1D.txt\n *                 https://introcs.cs.princeton.edu/java/22library/tinyDouble2D.txt\n *                 https://introcs.cs.princeton.edu/java/22library/tinyBoolean2D.txt\n *\n *  A library for reading in 1D and 2D arrays of integers, doubles,\n *  and booleans from standard input and printing them out to\n *  standard output.\n *\n *  % more tinyDouble1D.txt\n *  4\n *    .000  .246  .222  -.032\n *\n *  % more tinyDouble2D.txt\n *  4 3\n *    .000  .270  .000\n *    .246  .224 -.036\n *    .222  .176  .0893\n *   -.032  .739  .270\n *\n *  % more tinyBoolean2D.txt\n *  4 3\n *    1 1 0\n *    0 0 0\n *    0 1 1\n *    1 1 1\n *\n *  % cat tinyDouble1D.txt tinyDouble2D.txt tinyBoolean2D.txt | java StdArrayIO\n *  4\n *    0.00000   0.24600   0.22200  -0.03200\n *\n *  4 3\n *    0.00000   0.27000   0.00000\n *    0.24600   0.22400  -0.03600\n *    0.22200   0.17600   0.08930\n *    0.03200   0.73900   0.27000\n *\n *  4 3\n *  1 1 0\n *  0 0 0\n *  0 1 1\n *  1 1 1\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The <code>StdArrayIO</code> class provides static methods for reading\n *  in 1D and 2D arrays from standard input and printing out to\n *  standard output.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/22libary\">Section 2.2</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class StdArrayIO {\n\n    // it doesn't make sense to instantiate this class\n    private StdArrayIO() { }\n\n    /**\n     * Reads a 1D array of doubles from standard input and returns it.\n     *\n     * @return the 1D array of doubles\n     */\n    public static double[] readDouble1D() {\n        int n = StdIn.readInt();\n        double[] a = new double[n];\n        for (int i = 0; i < n; i++) {\n            a[i] = StdIn.readDouble();\n        }\n        return a;\n    }\n\n    /**\n     * Prints an array of doubles to standard output.\n     *\n     * @param a the 1D array of doubles\n     */\n    public static void print(double[] a) {\n        int n = a.length;\n        StdOut.println(n);\n        for (int i = 0; i < n; i++) {\n            StdOut.printf(\"%9.5f \", a[i]);\n        }\n        StdOut.println();\n    }\n\n    /**\n     * Reads a 2D array of doubles from standard input and returns it.\n     *\n     * @return the 2D array of doubles\n     */\n    public static double[][] readDouble2D() {\n        int m = StdIn.readInt();\n        int n = StdIn.readInt();\n        double[][] a = new double[m][n];\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < n; j++) {\n                a[i][j] = StdIn.readDouble();\n            }\n        }\n        return a;\n    }\n\n    /**\n     * Prints the 2D array of doubles to standard output.\n     *\n     * @param a the 2D array of doubles\n     */\n    public static void print(double[][] a) {\n        int m = a.length;\n        int n = a[0].length;\n        StdOut.println(m + \" \" + n);\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < n; j++) {\n                StdOut.printf(\"%9.5f \", a[i][j]);\n            }\n            StdOut.println();\n        }\n    }\n\n\n    /**\n     * Reads a 1D array of integers from standard input and returns it.\n     *\n     * @return the 1D array of integers\n     */\n    public static int[] readInt1D() {\n        int n = StdIn.readInt();\n        int[] a = new int[n];\n        for (int i = 0; i < n; i++) {\n            a[i] = StdIn.readInt();\n        }\n        return a;\n    }\n\n    /**\n     * Prints an array of integers to standard output.\n     *\n     * @param a the 1D array of integers\n     */\n    public static void print(int[] a) {\n        int n = a.length;\n        StdOut.println(n);\n        for (int i = 0; i < n; i++) {\n            StdOut.printf(\"%9d \", a[i]);\n        }\n        StdOut.println();\n    }\n\n    /**\n     * Reads a 2D array of integers from standard input and returns it.\n     *\n     * @return the 2D array of integers\n     */\n    public static int[][] readInt2D() {\n        int m = StdIn.readInt();\n        int n = StdIn.readInt();\n        int[][] a = new int[m][n];\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < n; j++) {\n                a[i][j] = StdIn.readInt();\n            }\n        }\n        return a;\n    }\n\n    /**\n     * Print a 2D array of integers to standard output.\n     *\n     * @param a the 2D array of integers\n     */\n    public static void print(int[][] a) {\n        int m = a.length;\n        int n = a[0].length;\n        StdOut.println(m + \" \" + n);\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < n; j++) {\n                StdOut.printf(\"%9d \", a[i][j]);\n            }\n            StdOut.println();\n        }\n    }\n\n    /**\n     * Reads a 1D array of booleans from standard input and returns it.\n     *\n     * @return the 1D array of booleans\n     */\n    public static boolean[] readBoolean1D() {\n        int n = StdIn.readInt();\n        boolean[] a = new boolean[n];\n        for (int i = 0; i < n; i++) {\n            a[i] = StdIn.readBoolean();\n        }\n        return a;\n    }\n\n    /**\n     * Prints a 1D array of booleans to standard output.\n     *\n     * @param a the 1D array of booleans\n     */\n    public static void print(boolean[] a) {\n        int n = a.length;\n        StdOut.println(n);\n        for (int i = 0; i < n; i++) {\n            if (a[i]) StdOut.print(\"1 \");\n            else      StdOut.print(\"0 \");\n        }\n        StdOut.println();\n    }\n\n    /**\n     * Reads a 2D array of booleans from standard input and returns it.\n     *\n     * @return the 2D array of booleans\n     */\n    public static boolean[][] readBoolean2D() {\n        int m = StdIn.readInt();\n        int n = StdIn.readInt();\n        boolean[][] a = new boolean[m][n];\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < n; j++) {\n                a[i][j] = StdIn.readBoolean();\n            }\n        }\n        return a;\n    }\n\n   /**\n     * Prints a 2D array of booleans to standard output.\n     *\n     * @param a the 2D array of booleans\n     */\n    public static void print(boolean[][] a) {\n        int m = a.length;\n        int n = a[0].length;\n        StdOut.println(m + \" \" + n);\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < n; j++) {\n                if (a[i][j]) StdOut.print(\"1 \");\n                else         StdOut.print(\"0 \");\n            }\n            StdOut.println();\n        }\n    }\n\n   /**\n     * Unit tests {@code StdArrayIO}.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // read and print an array of doubles\n        double[] a = StdArrayIO.readDouble1D();\n        StdArrayIO.print(a);\n        StdOut.println();\n\n        // read and print a matrix of doubles\n        double[][] b = StdArrayIO.readDouble2D();\n        StdArrayIO.print(b);\n        StdOut.println();\n\n        // read and print a matrix of doubles\n        boolean[][] d = StdArrayIO.readBoolean2D();\n        StdArrayIO.print(d);\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdAudio.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdAudio.java\n *  Execution:    java StdAudio\n *  Dependencies: none\n *\n *  Simple library for reading, writing, and manipulating audio.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport javax.sound.sampled.Clip;\n\nimport java.io.File;\nimport java.io.ByteArrayInputStream;\nimport java.io.InputStream;\nimport java.io.IOException;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\n\nimport java.util.LinkedList;\n\nimport javax.sound.sampled.AudioFileFormat;\nimport javax.sound.sampled.AudioFormat;\nimport javax.sound.sampled.AudioInputStream;\nimport javax.sound.sampled.AudioSystem;\nimport javax.sound.sampled.DataLine;\nimport javax.sound.sampled.LineUnavailableException;\nimport javax.sound.sampled.SourceDataLine;\nimport javax.sound.sampled.UnsupportedAudioFileException;\n\n/**\n *  The {@code StdAudio} class provides static methods for\n *  playing, reading, and saving audio.\n *  It uses a simple audio model that allows you\n *  to send one sample to the sound card at a time.\n *  Each sample is a real number between –1.0 and +1.0.\n *  The samples are played in real time using a sampling\n *  rate of 44,100 Hz.\n *  In addition to playing individual samples, standard audio supports\n *  reading, writing, and playing audio files in a variety of standard formats.\n *  <p>\n *  See {@link StdAudioStereo} for a version that supports\n *  <em>stereo</em> audio (separate left and right channels).\n *  <p>\n *  <b>Getting started.</b>\n *  To use this class, you must have {@code StdAudio} in your Java classpath.\n *  Here are three possible ways to do this:\n *  <ul>\n *  <li> If you ran our autoinstaller, use the commands\n *  {@code javac-introcs} and {@code java-introcs} (or {@code javac-algs4}\n *  and {@code java-algs4}) when compiling and executing. These commands\n *  add {@code stdlib.jar} (or {@code algs4.jar}) to the Java classpath, which\n *  provides access to {@code StdAudio}.\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  (or <a href = \"https://algs4.cs.princeton.edu/code/algs4.jar\">algs4.jar</a>)\n *  and add it to the Java classpath.\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdAudio.java\">StdAudio.java</a>\n *  and put it in the working directory.\n *  </ul>\n *  <p>\n *  As a test, cut-and-paste the following short program into your editor:\n *  <pre>\n *   public class TestStdAudio {\n *       public static void main(String[] args) {\n *           double freq = 440.0;\n *           for (int i = 0; i &lt; StdAudio.SAMPLE_RATE; i++) {\n *               double sample = 0.5 * Math.sin(2 * Math.PI * freq * i / StdAudio.SAMPLE_RATE);\n *               StdAudio.play(sample);\n *           }\n *           StdAudio.drain();\n *       }\n *   }\n *  </pre>\n *  <p>\n *  If you compile and execute the program, you should hear a pure tone\n *  whose frequency is concert A (440 Hz).\n *\n *  <p>\n *  <b>Playing audio samples.</b>\n *  You can use the following two methods to play individual audio samples:\n *  <ul>\n *  <li> {@link #play(double sample)}\n *  <li> {@link #play(double[] samples)}\n *  </ul>\n *  <p>\n *  Each method sends the specified sample (or samples) to the sound card.\n *  The individual samples are real numbers between –1.0 and +1.0. If a\n *  sample is outside this range, it will be <em>clipped</em> (rounded to\n *  –1.0 or +1.0). The samples are played in real time using a sampling\n *  rate of 44,100 Hz.\n *\n *  <p>\n *  <b>Playing audio files.</b>\n *  You can use the following method to play an audio file:\n *  <ul>\n *  <li> {@link #play(String filename)}\n *  </ul>\n *  <p>\n *  It plays an audio file (in WAVE, AU, AIFF, or MIDI format) and does\n *  not return until the audio file is finished playing. This can produce\n *  particularly striking programs with minimal code.\n *  For example, the following code fragment plays a drum loop:\n *\n *  <pre>\n *   while (true) {\n *       StdAudio.play(\"BassDrum.wav\");\n *       StdAudio.play(\"SnareDrum.wav\");\n *   }\n *  </pre>\n *\n *  The individual audio files\n *  (such as <a href = \"https://introcs.cs.princeton.edu/java/stdlib/BassDrum.wav\">BassDrum.wav</a>\n *  and <a href = \"https://introcs.cs.princeton.edu/java/stdlib/SnareDrum.wav\">SnareDrum.wav</a>)\n *  must be accessible to Java, typically\n *  by being in the same directory as the {@code .class} file.\n *  <p>\n *\n *  <b>Reading and writing audio files.</b>\n *  You can read and write audio files using the following two methods:\n *  <ul>\n *  <li> {@link #read(String filename)}\n *  <li> {@link #save(String filename, double[] samples)}\n *  </ul>\n *  <p>\n *  The first method reads audio samples from an audio file\n *  (in WAVE, AU, AIFF, or MIDI format)\n *  and returns them as a double array with values between –1.0 and +1.0.\n *  The second method saves the audio samples in the specified double array to an\n *  audio file (in WAVE, AU, or AIFF format).\n *\n *  <p>\n *  <b>Audio file formats.</b>\n *  {@code StdAudio} relies on the\n *  <a href = \"https://www.oracle.com/java/technologies/javase/jmf-211-formats.html\">Java Media Framework</a>\n *  for reading, writing, and playing audio files. You should be able to read or play files\n *  in WAVE, AU, AIFF, and MIDI formats and save them to WAVE, AU, and AIFF formats.\n *  The file extensions corresponding to WAVE, AU, AIFF, and MIDI files\n *  are {@code .wav}, {@code .au}, {@code .aiff}, and {@code .midi},\n *  respectively.\n *  Some systems support additional audio file formats, but probably not MP3 or M4A.\n *  <p>\n *  The Java Media Framework supports a variety of different <em>audio data formats</em>,\n *  which includes\n *  <ul>\n *  <Li> the sampling rate (e.g., 44,100 Hz);\n *  <li> the number of bits per sample per channel (e.g., 8-bit or 16-bit);\n *  <li> the number of channels (e.g., monaural or stereo);\n *  <li> the byte ordering (e.g., little endian or big endian); and\n *  <li> the encoding scheme (typically linear PCM).\n *  </ul>\n *  <p>\n *  When saving files, {@code StdAudio} uses a sampling rate of 44,100 Hz,\n *  16 bits per sample, monaural audio, little endian, and linear PCM encoding.\n *  When reading files, {@code StdAudio} converts to a sammpling rate of 44,100 Hz,\n *  with 16 bits per sample.\n *\n *  <p>\n *  <b>Recording audio.</b>\n *  You can use the following methods to record audio samples that are\n *  played as a result of calls to {@link #play(double sample)} or\n *  {@link #play(double[] samples)}.\n *  <ul>\n *  <li> {@link #startRecording()}\n *  <li> {@link #stopRecording()}\n *  </ul>\n *  <p>\n *  The method {@code startRecording()} begins recording audio.\n *  The method {@code stopRecording()} stops recording and returns the recorded\n *  samples as an array of doubles.\n *  <p>\n *  {@code StdAudio} does not currently support recording audio that calls\n *  {@code playInBackground()}.\n *  <p>\n *  <b>Playing audio files in a background thread.</b>\n *  You can use the following methods to play an audio file in a background thread\n *  (e.g., as a background score in your program).\n *  <ul>\n *  <li> {@link #playInBackground(String filename)}\n *  <li> {@link #stopInBackground()}\n *  </ul>\n *  <p>\n *  Each call to the first method plays the specified sound in a separate background\n *  thread. Unlike with the {@code play()} methods, your program will not wait\n *  for the samples to finish playing before continuing.\n *  It supports playing an audio file in WAVE, AU, AIFF, or MIDI format.\n *  It is possible to play\n *  multiple audio files simultaneously (in separate background threads).\n *  The second method stops the playing of all audio in background threads.\n *  <p>\n *  <b>Draining standard audio.</b>\n *  On some systems, your Java program may terminate before all of the samples have been\n *  sent to the sound card. To prevent this, it is recommend that you call the\n *  following method to indicate that you are done using standard audio:\n *  <ul>\n *  <li> {@link #drain()}\n *  </ul>\n *  <p>\n *  The method drains any samples queued to the sound card that have not yet been\n *  sent to the sound card.\n *  <p>\n *  <b>Reference.</b>\n *  For additional documentation,\n *  see <a href=\"https://introcs.cs.princeton.edu/15inout\">Section 1.5</a> of\n *  <em>Computer Science: An Interdisciplinary Approach</em>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdAudio {\n\n    /**\n     *  The sample rate: 44,100 Hz for CD quality audio.\n     */\n    public static final int SAMPLE_RATE = 44100;\n\n    private static final int BYTES_PER_SAMPLE = 2;       // 16-bit audio\n    private static final int BITS_PER_SAMPLE = 16;       // 16-bit audio\n    private static final int MAX_16_BIT = 32768;\n    private static final int SAMPLE_BUFFER_SIZE = 4096;\n\n    private static final int MONAURAL = 1;\n    private static final int STEREO = 2;\n    private static final boolean LITTLE_ENDIAN = false;\n    private static final boolean BIG_ENDIAN    = true;\n    private static final boolean SIGNED        = true;\n    private static final boolean UNSIGNED      = false;\n\n\n    private static SourceDataLine line;   // to play the sound\n    private static byte[] buffer;         // our internal buffer\n    private static int bufferSize = 0;    // number of samples currently in internal buffer\n\n    // queue of background Runnable objects\n    private static LinkedList<BackgroundRunnable> backgroundRunnables = new LinkedList<>();\n\n    // for recording audio\n    private static QueueOfDoubles recordedSamples = null;\n    private static boolean isRecording = false;\n\n    private StdAudio() {\n        // can not instantiate\n    }\n\n    // static initializer\n    static {\n        init();\n    }\n\n    // open up an audio stream\n    private static void init() {\n        try {\n            // 44,100 Hz, 16-bit audio, monaural, signed PCM, little endian\n            AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, MONAURAL, SIGNED, LITTLE_ENDIAN);\n            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);\n\n            line = (SourceDataLine) AudioSystem.getLine(info);\n            line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);\n\n            // the internal buffer is a fraction of the actual buffer size, this choice is arbitrary\n            // it gets divided because we can't expect the buffered data to line up exactly with when\n            // the sound card decides to push out its samples.\n            buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3];\n        }\n        catch (LineUnavailableException e) {\n            System.out.println(e.getMessage());\n        }\n\n        // no sound gets made before this call\n        line.start();\n    }\n\n    // get an AudioInputStream object from a file\n    private static AudioInputStream getAudioInputStreamFromFile(String filename) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename is null\");\n        }\n\n        try {\n            // first try to read file from local file system\n            File file = new File(filename);\n            if (file.exists()) {\n                return AudioSystem.getAudioInputStream(file);\n            }\n\n            // resource relative to .class file\n            InputStream is1 = StdAudio.class.getResourceAsStream(filename);\n            if (is1 != null) {\n                return AudioSystem.getAudioInputStream(is1);\n            }\n\n            // resource relative to classloader root\n            InputStream is2 = StdAudio.class.getClassLoader().getResourceAsStream(filename);\n            if (is2 != null) {\n                return AudioSystem.getAudioInputStream(is2);\n            }\n\n            // from URL (including jar file)\n            URI uri = new URI(filename);\n            if (uri.isAbsolute()) {\n                URL url = uri.toURL();\n                return AudioSystem.getAudioInputStream(url);\n            }\n            else throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\");\n        }\n        catch (IOException | URISyntaxException e) {\n            throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\", e);\n        }\n        catch (UnsupportedAudioFileException e) {\n            throw new IllegalArgumentException(\"file of unsupported audio file format: '\" + filename + \"'\", e);\n        }\n    }\n\n    /**\n     * Sends any queued samples to the sound card.\n     */\n    public static void drain() {\n        if (bufferSize > 0) {\n            line.write(buffer, 0, bufferSize);\n            bufferSize = 0;\n        }\n        line.drain();\n    }\n\n\n    /**\n     * Closes standard audio.\n     */\n/*\n    public static void close() {\n        drain();\n        line.stop();\n    }\n*/\n    /**\n     * Writes one sample (between –1.0 and +1.0) to standard audio.\n     * If the sample is outside the range, it will be clipped\n     * (rounded to –1.0 or +1.0).\n     *\n     * @param  sample the sample to play\n     * @throws IllegalArgumentException if the sample is {@code Double.NaN}\n     */\n    public static void play(double sample) {\n        if (Double.isNaN(sample)) throw new IllegalArgumentException(\"sample is NaN\");\n\n        // clip if outside [-1, +1]\n        if (sample < -1.0) sample = -1.0;\n        if (sample > +1.0) sample = +1.0;\n\n        // save sample if recording\n        if (isRecording) {\n            recordedSamples.enqueue(sample);\n        }\n\n        // convert to bytes\n        short s = (short) (MAX_16_BIT * sample);\n        if (sample == 1.0) s = Short.MAX_VALUE;   // special case since 32768 not a short\n        buffer[bufferSize++] = (byte) s;\n        buffer[bufferSize++] = (byte) (s >> 8);   // little endian\n\n        // send to sound card if buffer is full\n        if (bufferSize >= buffer.length) {\n            line.write(buffer, 0, buffer.length);\n            bufferSize = 0;\n        }\n    }\n\n    /**\n     * Writes the array of samples (between –1.0 and +1.0) to standard audio.\n     * If a sample is outside the range, it will be clipped.\n     *\n     * @param  samples the array of samples to play\n     * @throws IllegalArgumentException if any sample is {@code Double.NaN}\n     * @throws IllegalArgumentException if {@code samples} is {@code null}\n     */\n    public static void play(double[] samples) {\n        if (samples == null) throw new IllegalArgumentException(\"argument to play() is null\");\n        for (int i = 0; i < samples.length; i++) {\n            play(samples[i]);\n        }\n    }\n\n    /**\n     * Plays an audio file (in WAVE, AU, AIFF, or MIDI format) and waits for it to finish.\n     * The file extension must be either {@code .wav}, {@code .au},\n     * or {@code .aiff}.\n     *\n     * @param filename the name of the audio file\n     * @throws IllegalArgumentException if unable to play {@code filename}\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public static void play(String filename) {\n\n        // may not work for streaming file formats\n        if (isRecording) {\n            double[] samples = read(filename);\n            for (double sample : samples)\n                recordedSamples.enqueue(sample);\n        }\n\n        AudioInputStream ais = getAudioInputStreamFromFile(filename);\n        SourceDataLine line = null;\n        int BUFFER_SIZE = 4096; // 4K buffer\n        try {\n            AudioFormat audioFormat = ais.getFormat();\n            DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);\n            line = (SourceDataLine) AudioSystem.getLine(info);\n            line.open(audioFormat);\n            line.start();\n            byte[] samples = new byte[BUFFER_SIZE];\n            int count;\n            while ((count = ais.read(samples, 0, BUFFER_SIZE)) != -1) {\n                line.write(samples, 0, count);\n            }\n        }\n        catch (IOException | LineUnavailableException e) {\n            System.out.println(e);\n        }\n        finally {\n            if (line != null) {\n                line.drain();\n                line.close();\n            }\n        }\n    }\n\n\n    /**\n     * Reads audio samples from a file (in WAVE, AU, AIFF, or MIDI format)\n     * and returns them as a double array with values between –1.0 and +1.0.\n     * The file extension must be either {@code .wav}, {@code .au},\n     * or {@code .aiff}.\n     *\n     * @param  filename the name of the audio file\n     * @return the array of samples\n     */\n    public static double[] read(String filename) {\n        // 4K buffer (must be a multiple of 2 for monaural or 4 for stereo)\n        int READ_BUFFER_SIZE = 4096;\n\n        // create AudioInputStream from file\n        AudioInputStream fromAudioInputStream = getAudioInputStreamFromFile(filename);\n        AudioFormat fromAudioFormat = fromAudioInputStream.getFormat();\n\n        // normalize AudioInputStream to 44,100 Hz, 16-bit audio, monaural, signed PCM, little endian\n        // https://docs.oracle.com/javase/tutorial/sound/converters.html\n        AudioFormat toAudioFormat = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, MONAURAL, SIGNED, LITTLE_ENDIAN);\n        if (!AudioSystem.isConversionSupported(toAudioFormat, fromAudioFormat)) {\n            throw new IllegalArgumentException(\"system cannot convert from \" + fromAudioFormat + \" to \" + toAudioFormat);\n        }\n        AudioInputStream toAudioInputStream = AudioSystem.getAudioInputStream(toAudioFormat, fromAudioInputStream);\n\n        // extract the audio data and convert to a double[] with each sample between -1 and +1\n        try {\n            QueueOfDoubles queue = new QueueOfDoubles();\n            byte[] bytes = new byte[READ_BUFFER_SIZE];\n            int count;\n            while ((count = toAudioInputStream.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {\n\n                // little endian, monaural\n                for (int i = 0; i < count/2; i++) {\n                    double sample = ((short) (((bytes[2*i+1] & 0xFF) << 8) | (bytes[2*i] & 0xFF))) / ((double) MAX_16_BIT);\n                    queue.enqueue(sample);\n                }\n\n                // little endian, stereo (perhaps, for a future version that supports stereo)\n                /*\n                for (int i = 0; i < count/4; i++) {\n                    double left  = ((short) (((bytes[4*i + 1] & 0xFF) << 8) | (bytes[4*i + 0] & 0xFF))) / ((double) MAX_16_BIT);\n                    double right = ((short) (((bytes[4*i + 3] & 0xFF) << 8) | (bytes[4*i + 2] & 0xFF))) / ((double) MAX_16_BIT);\n                    double sample = (left + right) / 2.0;\n                    queue.enqueue(sample);\n                }\n                */\n            }\n            toAudioInputStream.close();\n            fromAudioInputStream.close();\n            return queue.toArray();\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\", ioe);\n        }\n    }\n\n    /**\n     * Saves the audio samples as an audio file (using WAV, AU, or AIFF format).\n     * The file extension must be either {@code .wav}, {@code .au},\n     * or {@code .aiff}.\n     * The format uses a sampling rate of 44,100 Hz, 16-bit audio,\n     * monaural, signed PCM, ands little Endian.\n     *\n     * @param  filename the name of the audio file\n     * @param  samples the array of samples\n     * @throws IllegalArgumentException if unable to save {@code filename}\n     * @throws IllegalArgumentException if {@code samples} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if {@code filename} extension is not\n     *         {@code .wav}, {@code .au}, or {@code .aiff}.\n     */\n    public static void save(String filename, double[] samples) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename is null\");\n        }\n        if (samples == null) {\n            throw new IllegalArgumentException(\"samples[] is null\");\n        }\n        if (filename.length() == 0) {\n            throw new IllegalArgumentException(\"argument to save() is the empty string\");\n        }\n\n        // assumes 16-bit samples with sample rate = 44,100 Hz\n        // use 16-bit audio, monaural, signed PCM, little Endian\n        AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, MONAURAL, SIGNED, LITTLE_ENDIAN);\n        byte[] data = new byte[2 * samples.length];\n        for (int i = 0; i < samples.length; i++) {\n            int temp = (short) (samples[i] * MAX_16_BIT);\n            if (samples[i] == 1.0) temp = Short.MAX_VALUE;   // special case since 32768 not a short\n            data[2*i + 0] = (byte) temp;\n            data[2*i + 1] = (byte) (temp >> 8);   // little endian\n        }\n\n\n        // now save the file\n        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);\n            AudioInputStream ais = new AudioInputStream(bais, format, samples.length)) {\n\n            if (filename.endsWith(\".wav\") || filename.endsWith(\".WAV\")) {\n                if (!AudioSystem.isFileTypeSupported(AudioFileFormat.Type.WAVE, ais)) {\n                    throw new IllegalArgumentException(\"saving to WAVE file format is not supported on this system\");\n                }\n                AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));\n            }\n            else if (filename.endsWith(\".au\") || filename.endsWith(\".AU\")) {\n                if (!AudioSystem.isFileTypeSupported(AudioFileFormat.Type.AU, ais)) {\n                    throw new IllegalArgumentException(\"saving to AU file format is not supported on this system\");\n                }\n                AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(filename));\n            }\n            else if (filename.endsWith(\".aif\") || filename.endsWith(\".aiff\") || filename.endsWith(\".AIF\") || filename.endsWith(\".AIFF\")) {\n                if (!AudioSystem.isFileTypeSupported(AudioFileFormat.Type.AIFF, ais)) {\n                    throw new IllegalArgumentException(\"saving to AIFF file format is not supported on this system\");\n                }\n                AudioSystem.write(ais, AudioFileFormat.Type.AIFF, new File(filename));\n            }\n            else {\n                throw new IllegalArgumentException(\"file extension for saving must be .wav, .au, or .aif\");\n            }\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"unable to save file '\" + filename + \"'\", ioe);\n        }\n    }\n\n    /**\n     * Stops the playing of all audio files in background threads.\n     */\n    public static synchronized void stopInBackground() {\n        for (BackgroundRunnable runnable : backgroundRunnables) {\n            runnable.stop();\n        }\n        backgroundRunnables.clear();\n    }\n\n    /**\n     * Plays an audio file (in WAVE, AU, AIFF, or MIDI format) in its own\n     * background thread. Multiple audio files can be played simultaneously.\n     * The file extension must be either {@code .wav}, {@code .au},\n     * or {@code .aiff}.\n     *\n     * @param filename the name of the audio file\n     * @throws IllegalArgumentException if unable to play {@code filename}\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public static synchronized void playInBackground(final String filename) {\n        BackgroundRunnable runnable = new BackgroundRunnable(filename);\n        new Thread(runnable).start();\n        backgroundRunnables.add(runnable);\n    }\n\n    private static class BackgroundRunnable implements Runnable {\n        private volatile boolean exit = false;\n        private final String filename;\n\n        public BackgroundRunnable(String filename) {\n            this.filename = filename;\n        }\n\n        // https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html\n        // play a wav or aif file\n        // javax.sound.sampled.Clip fails for long clips (on some systems)\n        public void run() {\n            AudioInputStream ais = getAudioInputStreamFromFile(filename);\n\n            SourceDataLine line = null;\n            int BUFFER_SIZE = 4096; // 4K buffer\n\n            try {\n                AudioFormat audioFormat = ais.getFormat();\n                DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);\n                line = (SourceDataLine) AudioSystem.getLine(info);\n                line.open(audioFormat);\n                line.start();\n                byte[] samples = new byte[BUFFER_SIZE];\n                int count;\n                while (!exit && (count = ais.read(samples, 0, BUFFER_SIZE)) != -1) {\n                    line.write(samples, 0, count);\n                }\n            }\n            catch (IOException | LineUnavailableException e) {\n                System.out.println(e);\n            }\n            finally {\n                if (line != null) {\n                    line.drain();\n                    line.close();\n                }\n                backgroundRunnables.remove(this);\n            }\n        }\n\n        public void stop() {\n            exit = true;\n        }\n    }\n\n\n    /**\n     * Loops an audio file (in WAVE, AU, AIFF, or MIDI format) in its\n     * own background thread.\n     *\n     * @param filename the name of the audio file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @deprecated to be removed in a future update, as it doesn't interact\n     *             well with {@link #playInBackground(String filename)} or\n     *             {@link #stopInBackground()}.\n     */\n    @Deprecated\n    public static synchronized void loopInBackground(String filename) {\n        if (filename == null) throw new IllegalArgumentException();\n\n        final AudioInputStream ais = getAudioInputStreamFromFile(filename);\n\n        try {\n            Clip clip = AudioSystem.getClip();\n            // Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));\n            clip.open(ais);\n            clip.loop(Clip.LOOP_CONTINUOUSLY);\n        }\n        catch (IOException | LineUnavailableException e) {\n            System.out.println(e);\n        }\n\n        // keep JVM open\n        new Thread(new Runnable() {\n            public void run() {\n                while (true) {\n                    try {\n                       Thread.sleep(1000);\n                    }\n                    catch (InterruptedException e) {\n                        System.out.println(e);\n                    }\n                }\n            }\n        }).start();\n    }\n\n\n    /**\n     * Turns on audio recording.\n     */\n    public static void startRecording() {\n        if (!isRecording) {\n            recordedSamples = new QueueOfDoubles();\n            isRecording = true;\n         }\n         else {\n             throw new IllegalStateException(\"startRecording() must not be called twice in a row\");\n         }\n    }\n\n    /**\n     * Turns off audio recording and returns the recorded samples.\n     * @return the array of recorded samples\n     */\n    public static double[] stopRecording() {\n        if (isRecording) {\n            double[] results = recordedSamples.toArray();\n            isRecording = false;\n            recordedSamples = null;\n            return results;\n        }\n        else {\n            throw new IllegalStateException(\"stopRecording() must be called after calling startRecording()\");\n        }\n    }\n\n\n   /***************************************************************************\n    * Helper class for reading and recording audio.\n    ***************************************************************************/\n    private static class QueueOfDoubles {\n        private static final int INIT_CAPACITY = 16;\n        private double[] a;   // array of doubles\n        private int n;        // number of items in queue\n\n        // create an empty queue\n        public QueueOfDoubles() {\n            a = new double[INIT_CAPACITY];\n            n = 0;\n        }\n\n        // resize the underlying array holding the items\n        private void resize(int capacity) {\n            assert capacity >= n;\n            double[] temp = new double[capacity];\n            for (int i = 0; i < n; i++)\n                temp[i] = a[i];\n            a = temp;\n        }\n\n        // enqueue item onto the queue\n        public void enqueue(double item) {\n            if (n == a.length) resize(2*a.length);    // double length of array if necessary\n            a[n++] = item;                            // add item\n        }\n\n\n        // number of items in queue\n        public int size() {\n            return n;\n        }\n\n        // return the items as an array of length n\n        public double[] toArray() {\n            double[] result = new double[n];\n            for (int i = 0; i < n; i++)\n                result[i] = a[i];\n            return result;\n        }\n\n    }\n\n\n    /**\n     * Test client - plays some sound files and concert A.\n     *\n     * @param args the command-line arguments (none should be specified)\n     */\n    public static void main(String[] args) {\n        // 440 Hz for 1 sec\n        double freq = 440.0;\n        for (int i = 0; i <= StdAudio.SAMPLE_RATE; i++) {\n            StdAudio.play(0.5 * Math.sin(2*Math.PI * freq * i / StdAudio.SAMPLE_RATE));\n        }\n\n\n        String base = \"https://introcs.cs.princeton.edu/java/stdlib/\";\n\n        // play some sound files\n        StdAudio.play(base + \"test.wav\");          // helicopter\n        StdAudio.play(base + \"test-22050.wav\");    // twenty-four\n        StdAudio.play(base + \"test.midi\");         // a Mozart measure\n\n        // a sound loop\n        for (int i = 0; i < 10; i++) {\n            StdAudio.play(base + \"BaseDrum.wav\");\n            StdAudio.play(base + \"SnareDrum.wav\");\n        }\n\n        // need to call this in non-interactive stuff so the program doesn't terminate\n        // until all the sound leaves the speaker.\n        StdAudio.drain();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdAudioStereo.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdAudioStereo.java\n *  Execution:    java StdAudioStereo\n *  Dependencies: none\n *\n *  Simple library for reading, writing, and manipulating audio.\n *\n *  Supported formats:\n *  https://www.oracle.com/java/technologies/javase/jmf-211-formats.html\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport javax.sound.sampled.Clip;\n\nimport java.io.File;\nimport java.io.ByteArrayInputStream;\nimport java.io.InputStream;\nimport java.io.IOException;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\n\nimport java.util.LinkedList;\n\nimport javax.sound.sampled.AudioFileFormat;\nimport javax.sound.sampled.AudioFormat;\nimport javax.sound.sampled.AudioInputStream;\nimport javax.sound.sampled.AudioSystem;\nimport javax.sound.sampled.DataLine;\nimport javax.sound.sampled.LineUnavailableException;\nimport javax.sound.sampled.SourceDataLine;\nimport javax.sound.sampled.UnsupportedAudioFileException;\n\n/**\n *  The {@code StdAudioStereo} class provides static methods for playing,\n *  reading, and saving stereo audio.\n *  It uses a simple audio model that allows\n *  you to send one pair of samples (left channel and right channel)\n *  to the sound card at a time. Each sample is a\n *  real number between –1.0 and +1.0. The samples are played in real\n *  time using a sampling rate of 44,100 Hz.\n *  In addition to playing individual pairs of samples, standard audio supports\n *  reading, writing, and playing audio files in a number of standard formats.\n *  <p>\n *  See {@link StdAudio} for a version that supports <em>monaural</em>\n *  audio (one channel only).\n *  <p>\n *  <b>Getting started.</b>\n *  To use this class, you must have {@code StdAudioStereo} in your Java classpath.\n *  Here are three possible ways to do this:\n *  <ul>\n *  <li> If you ran our autoinstaller, use the commands\n *  {@code javac-introcs} and {@code java-introcs} (or {@code javac-algs4}\n *  and {@code java-algs4}) when compiling and executing. These commands\n *  add {@code stdlib.jar} (or {@code algs4.jar}) to the Java classpath, which\n *  provides access to {@code StdAudioStereo}.\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  (or <a href = \"https://algs4.cs.princeton.edu/code/algs4.jar\">algs4.jar</a>)\n *  and add it to the Java classpath.\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdAudioStereo.java\">StdAudioStereo.java</a>\n *  and put it in the working directory.\n *  </ul>\n *  <p>\n *  As a test, cut-and-paste the following short program into your editor:\n *  <pre>\n *   public class TestStdAudioStereo {\n *       public static void main(String[] args) {\n *           double freq1 = 440.0;\n *           double freq2 = 220.0;\n *           for (int i = 0; i &lt; StdAudioStereo.SAMPLE_RATE; i++) {\n *               double sampleLeft  = 0.5 * Math.sin(2 * Math.PI * freq1 * i / StdAudioStereo.SAMPLE_RATE);\n *               double sampleRight = 0.5 * Math.sin(2 * Math.PI * freq2 * i / StdAudioStereo.SAMPLE_RATE);\n *               StdAudioStereo.play(sampleLeft, sampleRight);\n *           }\n *           StdAudioStereo.drain();\n *       }\n *   }\n *  </pre>\n *  <p>\n *  If you compile and execute the program, you should hear a pure tone\n *  whose frequency is <em>concert A</em> (440 Hz) in the left speaker\n *  and the pitch <em>A</em><sub>3</sub> (220 Hz) in the right speaker.\n *\n *  <p>\n *  <b>Playing audio samples.</b>\n *  You can use the following methods to play individual audio samples,\n *  either in monaural or stereo:\n *  <ul>\n *  <li> {@link #play(double sample)}\n *  <li> {@link #play(double[] samples)}\n *  <li> {@link #play(double sampleLeft, double sampleRight)}\n *  <li> {@link #play(double[] samplesLeft, double[] samplesRight)}\n *  </ul>\n *  <p>\n *  Each method sends the specified sample (or samples) to the sound card.\n *  The individual samples are real numbers between –1.0 and +1.0. If a\n *  sample is outside this range, it will be <em>clipped</em> (rounded to\n *  –1.0 or +1.0). The samples are played in real time using a sampling\n *  rate of 44,100 Hz.\n *\n *  <p>\n *  <b>Playing audio files.</b>\n *  You can use the following method to play an audio file:\n *  <ul>\n *  <li> {@link #play(String filename)}\n *  </ul>\n *  <p>\n *  It plays an audio file (in WAVE, AU, AIFF, or MIDI format) and does\n *  not return until the audio file is finished playing. This can produce\n *  particularly striking programs with minimal code.\n *  For example, the following code fragment plays a drum loop:\n *\n *  <pre>\n *   while (true) {\n *       StdAudioStereo.play(\"BassDrum.wav\");\n *       StdAudioStereo.play(\"SnareDrum.wav\");\n *   }\n *  </pre>\n *\n *  The individual audio files\n *  (such as <a href = \"https://introcs.cs.princeton.edu/java/stdlib/BassDrum.wav\">BassDrum.wav</a>\n *  and <a href = \"https://introcs.cs.princeton.edu/java/stdlib/SnareDrum.wav\">SnareDrum.wav</a>)\n *  must be accessible to Java, typically\n *  by being in the same directory as the {@code .class} file.\n *  <p>\n *\n *  <b>Reading and writing audio files.</b>\n *  You can read and write audio files using the following methods:\n *  <ul>\n *  <li> {@link #read(String filename)}\n *  <li> {@link #save(String filename, double[] samples)}\n *  <li> {@link #save(String filename, double[] samplesLeft, double[] samplesRight)}\n *  </ul>\n *  <p>\n *  The first method reads audio samples from an audio file\n *  (in WAVE, AU, AIFF, or MIDI format)\n *  and returns them as a double array with values between –1.0 and +1.0.\n *  The second two method saves the audio samples in the specified double array to an\n *  audio file (in WAVE, AU, or AIFF format), either in monaural or stereo.\n *\n *  <p>\n *  <b>Audio file formats.</b>\n *  {@code StdAudioStereo} relies on the\n *  <a href = \"https://www.oracle.com/java/technologies/javase/jmf-211-formats.html\">Java Media Framework</a>\n *  for reading, writing, and playing audio files. You should be able to read or play files\n *  in WAVE, AU, AIFF, and MIDI formats and save them to WAVE, AU, and AIFF formats.\n *  The file extensions corresponding to WAVE, AU, AIFF, and MIDI files\n *  are {@code .wav}, {@code .au}, {@code .aiff}, and {@code .midi},\n *  respectively.\n *  Some systems support additional audio file formats, but probably not MP3 or M4A.\n *  <p>\n *  The Java Media Framework supports a variety of different <em>audio data formats</em>,\n *  which includes\n *  <ul>\n *  <Li> the sampling rate (e.g., 44,100 Hz);\n *  <li> the number of bits per sample per channel (e.g., 8-bit or 16-bit);\n *  <li> the number of channels (e.g., monaural or stereo);\n *  <li> the byte ordering (e.g., little endian or big endian); and\n *  <li> the encoding scheme (typically linear PCM).\n *  </ul>\n *  <p>\n *  When saving files, {@code StdAudioStereo} uses a sampling rate of 44,100 Hz,\n *  16 bits per sample, stereo audio, little endian, and linear PCM encoding.\n *  When reading files, {@code StdAudioStereo} converts to a sammpling rate of 44,100 Hz,\n *  with 16 bits per sample.\n *\n *  <p>\n *  <b>Recording audio.</b>\n *  You can use the following methods to record audio samples that are\n *  played as a result of calls to\n *  {@link #play(double sample)},\n *  {@link #play(double sampleLeft, double sampleRight)},\n *  {@link #play(double[] samples)},\n *  {@link #play(double[] samplesLeft, double[] samplesRight)},\n *  or {@link #play(String filename)}:\n *  <ul>\n *  <li> {@link #startRecording()}\n *  <li> {@link #stopRecording()}\n *  <li> {@link #getRecordingMono()}\n *  <li> {@link #getRecordingLeft()}\n *  <li> {@link #getRecordingRight()}\n *  </ul>\n *  <p>\n *  The method {@code startRecording()} begins recording audio.\n *  The method {@code stopRecording()} stops recording.\n *  After calling {@code stopRecording()}, you can access the\n *  recorded left and right channels using\n *  {@code getRecordingLeft()} and {@code getRecordingRight()}.\n *  <p>\n *  {@code StdAudioStereo} does not currently support recording audio that calls\n *  {@code playInBackground()}.\n *  <p>\n *  <b>Playing audio files in a background thread.</b>\n *  You can use the following methods to play an audio file in a background thread\n *  (e.g., as a background score in your program).\n *  <ul>\n *  <li> {@link #playInBackground(String filename)}\n *  <li> {@link #stopInBackground()}\n *  </ul>\n *  <p>\n *  Each call to the first method plays the specified sound in a separate background\n *  thread. Unlike with the {@link play} methods, your program will not wait\n *  for the samples to finish playing before continuing.\n *  It supports playing an audio file in WAVE, AU, AIFF, or MIDI format.\n *  It is possible to play\n *  multiple audio files simultaneously (in separate background threads).\n *  The second method stops the playing of all audio in background threads.\n *  <p>\n *  <b>Draining standard audio.</b>\n *  On some systems, your Java program may terminate before all of the samples have been\n *  sent to the sound card. To prevent this, it is recommend that you call the\n *  following method to indicate that you are done using standard audio:\n *  <ul>\n *  <li> {@link #drain()}\n *  </ul>\n *  <p>\n *  The method drains any samples queued to the sound card that have not yet been\n *  sent to the sound card.\n *  <p>\n *  <b>Reference.</b>\n *  For additional documentation,\n *  see <a href=\"https://introcs.cs.princeton.edu/15inout\">Section 1.5</a> of\n *  <em>Computer Science: An Interdisciplinary Approach</em>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdAudioStereo {\n\n    /**\n     *  The sample rate: 44,100 Hz for CD quality audio.\n     */\n    public static final int SAMPLE_RATE = 44100;\n\n    private static final int BYTES_PER_SAMPLE = 2;       // 16-bit audio\n    private static final int BITS_PER_SAMPLE = 16;       // 16-bit audio\n    private static final int MAX_16_BIT = 32768;\n    private static final int BYTES_PER_FRAME = 4;        // 2 bytes per sample * 2 channels\n    private static final int SAMPLE_BUFFER_SIZE = 4096;  // should be a multiple of frame size\n\n    private static final int MONAURAL = 1;  // 1 channel\n    private static final int STEREO = 2;    // 2 channels\n\n    private static final boolean LITTLE_ENDIAN = false;\n    private static final boolean BIG_ENDIAN    = true;\n    private static final boolean UNSIGNED      = false;\n    private static final boolean SIGNED        = true;\n    private static final boolean LEFT_CHANNEL  = false;\n    private static final boolean RIGHT_CHANNEL = true;\n\n    private static SourceDataLine line;   // to play the sound\n    private static byte[] buffer;         // our internal buffer\n    private static int bufferSize = 0;    // number of samples currently in internal buffer\n\n    // queue of background runnables\n    private static LinkedList<BackgroundRunnable> backgroundRunnables = new LinkedList<>();\n\n    // for recording audio\n    private static QueueOfDoubles recordedSamplesLeft = null;\n    private static QueueOfDoubles recordedSamplesRight = null;\n    private static boolean isRecording = false;\n\n    private StdAudioStereo() {\n        // can not instantiate\n    }\n\n    // static initializer\n    static {\n        init();\n    }\n\n    // open up an audio stream\n    private static void init() {\n        try {\n            // 44,100 Hz, 16-bit audio, monaural, signed PCM, little endian\n            AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, STEREO, SIGNED, LITTLE_ENDIAN);\n            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);\n\n            line = (SourceDataLine) AudioSystem.getLine(info);\n            line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);\n\n            // the internal buffer is a fraction of the actual buffer size, this choice is arbitrary\n            // it gets divided because we can't expect the buffered data to line up exactly with when\n            // the sound card decides to push out its samples. The buffer length must be a multiple of 4.\n            buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE / 2];\n        }\n        catch (LineUnavailableException e) {\n            System.out.println(e.getMessage());\n        }\n\n        // no sound gets made before this call\n        line.start();\n    }\n\n    // get an AudioInputStream object from a file\n    private static AudioInputStream getAudioInputStreamFromFile(String filename) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename is null\");\n        }\n\n        try {\n            // first try to read file from local file system\n            File file = new File(filename);\n            if (file.exists()) {\n                return AudioSystem.getAudioInputStream(file);\n            }\n\n            // resource relative to .class file\n            InputStream is1 = StdAudioStereo.class.getResourceAsStream(filename);\n            if (is1 != null) {\n                return AudioSystem.getAudioInputStream(is1);\n            }\n\n            // resource relative to classloader root\n            InputStream is2 = StdAudioStereo.class.getClassLoader().getResourceAsStream(filename);\n            if (is2 != null) {\n                return AudioSystem.getAudioInputStream(is2);\n            }\n\n            // from URL (including jar file)\n            URI uri = new URI(filename);\n            if (uri.isAbsolute()) {\n                URL url = uri.toURL();\n                return AudioSystem.getAudioInputStream(url);\n            }\n            else throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\");\n        }\n        catch (IOException | URISyntaxException e) {\n            throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\");\n        }\n        catch (UnsupportedAudioFileException e) {\n            throw new IllegalArgumentException(\"file of unsupported audio file format: '\" + filename + \"'\", e);\n        }\n    }\n\n    /**\n     * Sends any queued samples to the sound card.\n     */\n    public static void drain() {\n        if (bufferSize > 0) {\n            line.write(buffer, 0, bufferSize);\n            bufferSize = 0;\n        }\n        line.drain();\n    }\n\n\n    /**\n     * Closes standard audio.\n     */\n/*\n    public static void close() {\n        drain();\n        line.stop();\n    }\n*/\n\n    /**\n     * Writes one stereo sample (between –1.0 and +1.0) to standard audio.\n     * If the sample is outside the range, it will be clipped\n     * (rounded to –1.0 or +1.0).\n     *\n     * @param  sampleLeft the left sample to play\n     * @param  sampleRight the right sample to play\n     * @throws IllegalArgumentException if either\n     *         {@code sampleLeft} or {@code sampleRight} is {@code Double.NaN}\n     */\n    public static void play(double sampleLeft, double sampleRight) {\n        if (Double.isNaN(sampleLeft)) throw new IllegalArgumentException(\"sampleLeft is NaN\");\n        if (Double.isNaN(sampleRight)) throw new IllegalArgumentException(\"sampleRight is NaN\");\n\n        // clip if outside [-1, +1]\n        if (sampleLeft < -1.0) sampleLeft = -1.0;\n        if (sampleLeft > +1.0) sampleLeft = +1.0;\n        if (sampleRight < -1.0) sampleRight = -1.0;\n        if (sampleRight > +1.0) sampleRight = +1.0;\n\n        // save sample if recording\n        if (isRecording) {\n            recordedSamplesLeft.enqueue(sampleLeft);\n            recordedSamplesRight.enqueue(sampleRight);\n        }\n\n        // convert left sample to bytes\n        short sLeft = (short) (MAX_16_BIT * sampleLeft);\n        if (sampleLeft == 1.0) sLeft = Short.MAX_VALUE;   // special case since 32768 not a short\n        buffer[bufferSize++] = (byte) sLeft;\n        buffer[bufferSize++] = (byte) (sLeft >> 8);   // little endian\n\n        // convert right sample to bytes\n        short sRight = (short) (MAX_16_BIT * sampleRight);\n        if (sampleRight == 1.0) sRight = Short.MAX_VALUE;\n        buffer[bufferSize++] = (byte) sRight;\n        buffer[bufferSize++] = (byte) (sRight >> 8);   // little endian\n\n        // send to sound card if buffer is full\n        if (bufferSize >= buffer.length) {\n            line.write(buffer, 0, buffer.length);\n            bufferSize = 0;\n        }\n    }\n\n    /**\n     * Writes one sample (between –1.0 and +1.0) to standard audio.\n     * If the sample is outside the range, it will be clipped\n     * (rounded to –1.0 or +1.0).\n     *\n     * @param  sample the sample to play\n     * @throws IllegalArgumentException if {@code sample} is {@code Double.NaN}\n     */\n    public static void play(double sample) {\n        play(sample, sample);\n    }\n\n    /**\n     * Writes the array of samples (between –1.0 and +1.0) to standard audio.\n     * If a sample is outside the range, it will be clipped.\n     *\n     * @param  samples the array of samples to play\n     * @throws IllegalArgumentException if any sample is {@code Double.NaN}\n     * @throws IllegalArgumentException if {@code samples} is {@code null}\n     */\n    public static void play(double[] samples) {\n        if (samples == null) throw new IllegalArgumentException(\"argument to play() is null\");\n        for (int i = 0; i < samples.length; i++) {\n            play(samples[i]);\n        }\n    }\n\n    /**\n     * Writes the array of stereo samples (between –1.0 and +1.0) to standard audio.\n     * If a sample is outside the range, it will be clipped.\n     *\n     * @param  samplesLeft the array of samples for the left channel to play\n     * @param  samplesRight the array of samples for the right channel to play\n     * @throws IllegalArgumentException if any sample is {@code Double.NaN}\n     * @throws IllegalArgumentException if either\n     *         {@code samplesLeft} or {@code samplesRight} is {@code null}\n     * @throws IllegalArgumentException if {@code samplesLeft.length != samplesRight.length}\n     */\n    public static void play(double[] samplesLeft, double[] samplesRight) {\n        if (samplesLeft == null) throw new IllegalArgumentException(\"argument to play() is null\");\n        if (samplesRight == null) throw new IllegalArgumentException(\"argument to play() is null\");\n        if (samplesLeft.length != samplesRight.length) throw new IllegalArgumentException(\"left and right arrays have different lengths\");\n\n        for (int i = 0; i < samplesLeft.length; i++) {\n            play(samplesLeft[i], samplesRight[i]);\n        }\n    }\n\n    /**\n     * Plays an audio file (in WAVE, AU, AIFF, or MIDI format) and waits for it to finish.\n     *\n     * @param filename the name of the audio file\n     * @throws IllegalArgumentException if unable to play {@code filename}\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public static void play(String filename) {\n\n        // may not work for streaming file formats\n        if (isRecording) {\n            double[] samplesLeft = readLeft(filename);\n            double[] samplesRight = readRight(filename);\n            for (double sample : samplesLeft)\n                recordedSamplesLeft.enqueue(sample);\n            for (double sample : samplesRight)\n                recordedSamplesRight.enqueue(sample);\n        }\n\n        AudioInputStream ais = getAudioInputStreamFromFile(filename);\n        SourceDataLine line = null;\n        int BUFFER_SIZE = 4096; // 4K buffer\n        try {\n            AudioFormat audioFormat = ais.getFormat();\n            DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);\n            line = (SourceDataLine) AudioSystem.getLine(info);\n            line.open(audioFormat);\n            line.start();\n            byte[] samples = new byte[BUFFER_SIZE];\n            int count = 0;\n            while ((count = ais.read(samples, 0, BUFFER_SIZE)) != -1) {\n                line.write(samples, 0, count);\n            }\n        }\n        catch (IOException | LineUnavailableException e) {\n            System.out.println(e);\n        }\n        finally {\n            if (line != null) {\n                line.drain();\n                line.close();\n            }\n        }\n    }\n\n\n    // helper method to read the left or right channel from the given audio file and return as a double[]\n    private static double[] readChannel(String filename, boolean channel) {\n        // 4K buffer (must be a multiple of 4 for stereo)\n        int READ_BUFFER_SIZE = 4096;\n\n        // create AudioInputStream from file\n        AudioInputStream fromAudioInputStream = getAudioInputStreamFromFile(filename);\n        AudioFormat fromAudioFormat = fromAudioInputStream.getFormat();\n\n        // normalize AudioInputStream to 44,100 Hz, 16-bit audio, stereo, signed PCM, little endian\n        // https://docs.oracle.com/javase/tutorial/sound/converters.html\n        AudioFormat toAudioFormat = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, STEREO, SIGNED, LITTLE_ENDIAN);\n        if (!AudioSystem.isConversionSupported(toAudioFormat, fromAudioFormat)) {\n            throw new IllegalArgumentException(\"system cannot convert from \" + fromAudioFormat + \" to \" + toAudioFormat);\n        }\n        AudioInputStream toAudioInputStream = AudioSystem.getAudioInputStream(toAudioFormat, fromAudioInputStream);\n\n        // extract the audio data and convert to a double[] with each sample between -1 and +1\n        try {\n            QueueOfDoubles queue = new QueueOfDoubles();\n            int count = 0;\n            byte[] bytes = new byte[READ_BUFFER_SIZE];\n            while ((count = toAudioInputStream.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {\n                // little endian, stereo (perhaps, for a future version that supports stereo)\n                for (int i = 0; i < count/4; i++) {\n                    double left  = ((short) (((bytes[4*i + 1] & 0xFF) << 8) | (bytes[4*i + 0] & 0xFF))) / ((double) MAX_16_BIT);\n                    double right = ((short) (((bytes[4*i + 3] & 0xFF) << 8) | (bytes[4*i + 2] & 0xFF))) / ((double) MAX_16_BIT);\n                    if (channel == LEFT_CHANNEL) queue.enqueue(left);\n                    else                         queue.enqueue(right);\n                }\n            }\n            toAudioInputStream.close();\n            fromAudioInputStream.close();\n            return queue.toArray();\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\", ioe);\n        }\n    }\n\n    /**\n     * Reads the audio samples (left channel) from an audio file\n     * (in WAVE, AU, AIFF, or MIDI format)\n     * and returns them as a double array with values between –1.0 and +1.0.\n     * The file can be any audio file supported by the Java Media Framework;\n     * if the audio data format is monaural,\n     * then {@link readLeft(String filename)}\n     * and {@link readRight(String filename)}\n     * will return the same sequence of values.\n     *\n     * @param  filename the name of the audio file\n     * @return the array of samples\n     */\n    public static double[] readLeft(String filename) {\n        return readChannel(filename, LEFT_CHANNEL);\n    }\n\n    /**\n     * Reads the audio samples (right channel) from an audio file\n     * (in WAVE, AU, AIFF, or MIDI format)\n     * and returns them as a double array with values between –1.0 and +1.0.\n     * The file can be any audio file supported by the Java Media Framework;\n     * if the audio data format is monaural,\n     * then {@link readLeft(String filename)}\n     * and {@link readRight(String filename)}\n     * will return the same sequence of values.\n     *\n     * @param  filename the name of the audio file\n     * @return the array of samples\n     */\n    public static double[] readRight(String filename) {\n        return readChannel(filename, RIGHT_CHANNEL);\n    }\n\n\n    /**\n     * Reads the audio samples from a file (in WAVE, AU, AIFF, or MIDI format)\n     * and returns them as a double array with values between –1.0 and +1.0.\n     * The samples returned use 16-bit audio data, a sampling rate of 44,100,\n     * and monaural audio.\n     * The file can be any audio file supported by the Java Media Framework;\n     * if the audio data format is stereo, it is first converted\n     * to monaural.\n     *\n     * @param  filename the name of the audio file\n     * @return the array of samples\n     */\n    public static double[] read(String filename) {\n        // 4K buffer (must be a multiple of 2 for monaural)\n        int READ_BUFFER_SIZE = 4096;\n\n        // create AudioInputStream from file\n        AudioInputStream fromAudioInputStream = getAudioInputStreamFromFile(filename);\n        AudioFormat fromAudioFormat = fromAudioInputStream.getFormat();\n\n        // normalize AudioInputStream to 44,100 Hz, 16-bit audio, monaural, signed PCM, little endian\n        // https://docs.oracle.com/javase/tutorial/sound/converters.html\n        AudioFormat toAudioFormat = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, MONAURAL, SIGNED, LITTLE_ENDIAN);\n        if (!AudioSystem.isConversionSupported(toAudioFormat, fromAudioFormat)) {\n            throw new IllegalArgumentException(\"system cannot convert from \" + fromAudioFormat + \" to \" + toAudioFormat);\n        }\n        AudioInputStream toAudioInputStream = AudioSystem.getAudioInputStream(toAudioFormat, fromAudioInputStream);\n\n        // extract the audio data and convert to a double[] with each sample between -1 and +1\n        try {\n            QueueOfDoubles queue = new QueueOfDoubles();\n            int count = 0;\n            byte[] bytes = new byte[READ_BUFFER_SIZE];\n            while ((count = toAudioInputStream.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {\n\n                // little endian, monaural\n                for (int i = 0; i < count/2; i++) {\n                    double sample = ((short) (((bytes[2*i+1] & 0xFF) << 8) | (bytes[2*i] & 0xFF))) / ((double) MAX_16_BIT);\n                    queue.enqueue(sample);\n                }\n            }\n            toAudioInputStream.close();\n            fromAudioInputStream.close();\n            return queue.toArray();\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"could not read audio file '\" + filename + \"'\", ioe);\n        }\n    }\n\n\n    // helper method to save a file in specifed format\n    private static void save(String filename, byte[] data, AudioFormat format, long numberOfFrames) {\n        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);\n            AudioInputStream ais = new AudioInputStream(bais, format, numberOfFrames)) {\n\n            if (filename.endsWith(\".wav\") || filename.endsWith(\".WAV\")) {\n                if (!AudioSystem.isFileTypeSupported(AudioFileFormat.Type.WAVE, ais)) {\n                    throw new IllegalArgumentException(\"saving to WAVE file format is not supported on this system\");\n                }\n                AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));\n            }\n            else if (filename.endsWith(\".au\") || filename.endsWith(\".AU\")) {\n                if (!AudioSystem.isFileTypeSupported(AudioFileFormat.Type.AU, ais)) {\n                    throw new IllegalArgumentException(\"saving to AU file format is not supported on this system\");\n                }\n                AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(filename));\n            }\n            else if (filename.endsWith(\".aif\") || filename.endsWith(\".aiff\") || filename.endsWith(\".AIF\") || filename.endsWith(\".AIFF\")) {\n                if (!AudioSystem.isFileTypeSupported(AudioFileFormat.Type.AIFF, ais)) {\n                    throw new IllegalArgumentException(\"saving to AIFF file format is not supported on this system\");\n                }\n                AudioSystem.write(ais, AudioFileFormat.Type.AIFF, new File(filename));\n            }\n            else {\n                throw new IllegalArgumentException(\"file extension for saving must be .wav, .au, or .aif\");\n            }\n        }\n        catch (IOException ioe) {\n            throw new IllegalArgumentException(\"unable to save file '\" + filename + \"'\", ioe);\n        }\n    }\n\n    /**\n     * Saves the audio samples as an <em>monaural</em> audio file\n     * (in WAV, AU, or AIFF format).\n     * The file extension type must be either {@code .wav}, {@code .au},\n     * or {@code .aiff}.\n     * The audio data format uses a sampling rate of 44,100 Hz, 16-bit audio,\n     * monaural, signed PCM, ands little endian.\n     *\n     * @param  filename the name of the audio file\n     * @param  samples the array of samples to save\n     * @throws IllegalArgumentException if unable to save {@code filename}\n     * @throws IllegalArgumentException if {@code samples} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} extension is not\n     *         {@code .wav}, {@code .au}, or {@code .aiff}.\n     */\n    public static void save(String filename, double[] samples) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename is null\");\n        }\n        if (samples == null) {\n            throw new IllegalArgumentException(\"samples[] is null\");\n        }\n        if (filename.length() == 0) {\n            throw new IllegalArgumentException(\"argument to save() is the empty string\");\n        }\n\n        // assumes 16-bit samples with sample rate = 44,100 Hz\n        // use 16-bit audio, monaural, signed PCM, little Endian\n        AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, MONAURAL, SIGNED, LITTLE_ENDIAN);\n        byte[] data = new byte[2 * samples.length];\n        for (int i = 0; i < samples.length; i++) {\n            int temp = (short) (samples[i] * MAX_16_BIT);\n            if (samples[i] == 1.0) temp = Short.MAX_VALUE;   // special case since 32768 not a short\n            data[2*i + 0] = (byte) temp;\n            data[2*i + 1] = (byte) (temp >> 8);   // little endian\n        }\n\n        // now save the file\n        save(filename, data, format, samples.length);\n    }\n\n\n    /**\n     * Saves the stereo samples as a <em>stereo</em> audio file\n     * (in WAV, AU, or AIFF format).\n     * The file extension type must be either {@code .wav}, {@code .au},\n     * or {@code .aiff}.\n     * The audio data format uses a sampling rate of 44,100 Hz, 16-bit audio,\n     * stereo, signed PCM, ands little endian.\n     *\n     * @param  filename the name of the audio file\n     * @param  samplesLeft the array of samples in left channel to save\n     * @param  samplesRight the array of samples in right channel to save\n     * @throws IllegalArgumentException if unable to save {@code filename}\n     * @throws IllegalArgumentException if {@code samplesLeft} is {@code null}\n     * @throws IllegalArgumentException if {@code samplesRight} is {@code null}\n     * @throws IllegalArgumentException if {@code samplesLeft.length != samplesRight.length}\n     * @throws IllegalArgumentException if {@code filename} extension is not\n     *         {@code .wav}, {@code .au}, or {@code .aiff}.\n     */\n    public static void save(String filename, double[] samplesLeft, double[] samplesRight) {\n        if (filename == null) {\n            throw new IllegalArgumentException(\"filename is null\");\n        }\n        if (samplesLeft == null) {\n            throw new IllegalArgumentException(\"samplesLeft[] is null\");\n        }\n        if (samplesRight == null) {\n            throw new IllegalArgumentException(\"samplesRight[] is null\");\n        }\n        if (samplesLeft.length != samplesRight.length) {\n            throw new IllegalArgumentException(\"input arrays have different lengths\");\n        }\n        // assumes 16-bit samples with sample rate = 44,100 Hz\n        // use 16-bit audio, monaural, signed PCM, little Endian\n        AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, STEREO, SIGNED, LITTLE_ENDIAN);\n        byte[] data = new byte[4 * samplesLeft.length];\n        for (int i = 0; i < samplesLeft.length; i++) {\n            int tempLeft = (short) (samplesLeft[i] * MAX_16_BIT);\n            int tempRight = (short) (samplesRight[i] * MAX_16_BIT);\n            if (samplesLeft[i] == 1.0) tempLeft = Short.MAX_VALUE;   // special case since 32768 not a short\n            if (samplesRight[i] == 1.0) tempRight = Short.MAX_VALUE;\n            data[4*i + 0] = (byte) tempLeft;\n            data[4*i + 1] = (byte) (tempLeft >> 8);   // little endian\n            data[4*i + 2] = (byte) tempRight;\n            data[4*i + 3] = (byte) (tempRight >> 8);\n        }\n\n        // now save the file\n        save(filename, data, format, samplesLeft.length);\n    }\n\n    /**\n     * Stops the playing of all audio files in background threads.\n     */\n    public static synchronized void stopInBackground() {\n        for (BackgroundRunnable runnable : backgroundRunnables) {\n            runnable.stop();\n        }\n        backgroundRunnables.clear();\n    }\n\n    /**\n     * Plays an audio file (in WAVE, AU, AIFF, or MIDI format) in its own\n     * background thread. Multiple audio files can be played simultaneously.\n     *\n     * @param filename the name of the audio file\n     * @throws IllegalArgumentException if unable to play {@code filename}\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public static synchronized void playInBackground(final String filename) {\n        BackgroundRunnable runnable = new BackgroundRunnable(filename);\n        new Thread(runnable).start();\n        backgroundRunnables.add(runnable);\n    }\n\n    private static class BackgroundRunnable implements Runnable {\n        private volatile boolean exit = false;\n        private final String filename;\n\n        public BackgroundRunnable(String filename) {\n            this.filename = filename;\n        }\n\n        // https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html\n        // play a wav or aif file\n        // javax.sound.sampled.Clip fails for long clips (on some systems)\n        public void run() {\n            AudioInputStream ais = getAudioInputStreamFromFile(filename);\n\n            SourceDataLine line = null;\n            int BUFFER_SIZE = 4096; // 4K buffer\n\n            try {\n                AudioFormat audioFormat = ais.getFormat();\n                DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);\n                line = (SourceDataLine) AudioSystem.getLine(info);\n                line.open(audioFormat);\n                line.start();\n                byte[] samples = new byte[BUFFER_SIZE];\n                int count = 0;\n                while (!exit && (count = ais.read(samples, 0, BUFFER_SIZE)) != -1) {\n                    line.write(samples, 0, count);\n                }\n            }\n            catch (IOException | LineUnavailableException e) {\n                System.out.println(e);\n            }\n            finally {\n                if (line != null) {\n                    line.drain();\n                    line.close();\n                }\n                backgroundRunnables.remove(this);\n            }\n        }\n\n        public void stop() {\n            exit = true;\n        }\n    }\n\n\n    /**\n     * Loops an audio file (in WAVE, AU, AIFF, or MIDI format) in its\n     * own background thread.\n     *\n     * @param filename the name of the audio file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @deprecated to be removed in a future update, as it doesn't interact\n     *             well with {@link #playInBackground(String filename)} or\n     *             {@link #stopInBackground()}.\n     */\n    @Deprecated\n    public static synchronized void loopInBackground(String filename) {\n        if (filename == null) throw new IllegalArgumentException();\n\n        final AudioInputStream ais = getAudioInputStreamFromFile(filename);\n\n        try {\n            Clip clip = AudioSystem.getClip();\n            // Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));\n            clip.open(ais);\n            clip.loop(Clip.LOOP_CONTINUOUSLY);\n        }\n        catch (IOException | LineUnavailableException e) {\n            System.out.println(e);\n        }\n\n        // keep JVM open\n        new Thread(new Runnable() {\n            public void run() {\n                while (true) {\n                    try {\n                       Thread.sleep(1000);\n                    }\n                    catch (InterruptedException e) {\n                        System.out.println(e);\n                    }\n                }\n            }\n        }).start();\n    }\n\n\n    /**\n     * Starts recording audio samples.\n     * This includes all calls to {@code play()} that take samples as arguments,\n     * but not calls to {@code play()} that play audio files.\n     *\n     * @throws IllegalArgumentException if recording mode is already on\n     */\n    public static void startRecording() {\n        if (!isRecording) {\n            recordedSamplesLeft = new QueueOfDoubles();\n            recordedSamplesRight = new QueueOfDoubles();\n            isRecording = true;\n         }\n         else {\n             throw new IllegalStateException(\"startRecording() must not be called twice in a row\");\n         }\n    }\n\n    /**\n     * Stops recording audio samples.\n     *\n     * @throws IllegalArgumentException if recording mode is not currently on\n     */\n    public static void stopRecording() {\n        if (isRecording) {\n            isRecording = false;\n        }\n        else {\n            throw new IllegalStateException(\"stopRecording() must be called after calling startRecording()\");\n        }\n    }\n\n    /**\n     * Returns the array of samples that was recorded in the left channel in\n     * between the last calls to {@link startRecording()} and {@link stopRecording()}.\n     *\n     * @return the array of samples\n     * @throws IllegalArgumentException unless {@code startRecording} and\n     *         {@code stopRecording} were previously called in the appropriate order\n     */\n    public static double[] getRecordingLeft() {\n        if (recordedSamplesRight != null) {\n           throw new IllegalStateException(\"getRecordingLeft() must be called after startRecording()\");\n        }\n\n        if (isRecording) {\n            throw new IllegalStateException(\"getRecordingLeft() must be called after stopRecording()\");\n        }\n\n        double[] results = recordedSamplesLeft.toArray();\n        return results;\n    }\n\n    /**\n     * Returns the array of samples that was recorded in the right channel in\n     * between the last calls to {@link startRecording()} and {@link stopRecording()}.\n     *\n     * @return the array of samples\n     * @throws IllegalArgumentException unless {@code startRecording} and\n     *         {@code stopRecording} were previously called in the appropriate order\n     */\n    public static double[] getRecordingRight() {\n        if (recordedSamplesRight != null) {\n           throw new IllegalStateException(\"getRecordingRight() must be called after startRecording()\");\n        }\n\n        if (isRecording) {\n            throw new IllegalStateException(\"getRecordingRight() must be called after stopRecording()\");\n        }\n\n        double[] result = recordedSamplesRight.toArray();\n        return result;\n    }\n\n    /**\n     * Returns the array of samples that was recorded in the right channel in\n     * between the last calls to {@link startRecording()} and {@link stopRecording()},\n     * by taking the average of the samples in the left and right channels.\n     *\n     * @return the array of samples\n     * @throws IllegalArgumentException unless {@code startRecording} and\n     *         {@code stopRecording} were previously called in the appropriate order\n     */\n    public static double[] getRecordingMono() {\n        if (recordedSamplesRight != null) {\n           throw new IllegalStateException(\"getRecording() must be called after startRecording()\");\n        }\n\n        if (isRecording) {\n            throw new IllegalStateException(\"getRecording() must be called after stopRecording()\");\n        }\n\n        double[] left = getRecordingLeft();\n        double[] right = getRecordingRight();\n        int n = left.length;\n        double[] sum = new double[n];\n        for (int i = 0; i < left.length; i++) {\n            sum[i] = 0.5 * (left[i] + right[i]);\n        }\n        return sum;\n    }\n\n   /***************************************************************************\n    * Helper class for reading and recording audio.\n    ***************************************************************************/\n    private static class QueueOfDoubles {\n        private final static int INIT_CAPACITY = 16;\n        private double[] a;   // array of doubles\n        private int n;        // number of items in queue\n\n        // create an empty queue\n        public QueueOfDoubles() {\n            a = new double[INIT_CAPACITY];\n            n = 0;\n        }\n\n        // resize the underlying array holding the items\n        private void resize(int capacity) {\n            assert capacity >= n;\n            double[] temp = new double[capacity];\n            for (int i = 0; i < n; i++)\n                temp[i] = a[i];\n            a = temp;\n        }\n\n        // enqueue item onto the queue\n        public void enqueue(double item) {\n            if (n == a.length) resize(2*a.length);    // double length of array if necessary\n            a[n++] = item;                            // add item\n        }\n\n\n        // number of items in queue\n        public int size() {\n            return n;\n        }\n\n        // return the items as an array of length n\n        public double[] toArray() {\n            double[] result = new double[n];\n            for (int i = 0; i < n; i++)\n                result[i] = a[i];\n            return result;\n        }\n\n    }\n\n\n    /**\n     * Test client - plays some sound files and concert A.\n     *\n     * @param args the command-line arguments (none should be specified)\n     */\n    public static void main(String[] args) {\n        // 440 Hz (left speaker) and 220Hz (right speaker) for 1 second\n        double freq1 = 440.0;\n        double freq2 = 220.0;\n        for (int i = 0; i <= StdAudioStereo.SAMPLE_RATE; i++) {\n            double sampleLeft  = 0.5 * Math.sin(2*Math.PI * freq1 * i / StdAudioStereo.SAMPLE_RATE);\n            double sampleRight = 0.5 * Math.sin(2*Math.PI * freq2 * i / StdAudioStereo.SAMPLE_RATE);\n            StdAudioStereo.play(sampleLeft, sampleRight);\n        }\n\n\n        // play some sound files\n        String base = \"https://introcs.cs.princeton.edu/java/stdlib/\";\n        StdAudioStereo.play(base + \"test.wav\");          // helicopter\n        StdAudioStereo.play(StdAudioStereo.readLeft(base + \"test.midi\"), StdAudioStereo.readRight(base + \"test.midi\"));\n\n        // a sound loop\n        for (int i = 0; i < 10; i++) {\n            StdAudioStereo.play(base + \"BassDrum.wav\");\n            StdAudioStereo.play(base + \"SnareDrum.wav\");\n        }\n\n        // need to call this in non-interactive stuff so the program doesn't terminate\n        // until all the sound leaves the speaker.\n        StdAudioStereo.drain();\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdDraw.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdDraw.java\n *  Execution:    java StdDraw\n *  Dependencies: none\n *\n *  Standard drawing library. This class provides a basic capability for\n *  creating drawings with your programs. It uses a simple graphics model that\n *  allows you to create drawings consisting of geometric shapes (e.g.,\n *  points, lines, circles, rectangles) in a window on your computer\n *  and to save the drawings to a file.\n *\n *  Todo\n *  ----\n *    -  Don't show window until first unbuffered drawing command or call to show()\n *       (with setVisible not set to false).\n *    -  Add support for gradient fill, etc.\n *    -  Fix setCanvasSize() so that it can be called only once.\n *    -  On some systems, drawing a line (or other shape) that extends way\n *       beyond canvas (e.g., to infinity) dimensions does not get drawn.\n *\n *  Remarks\n *  -------\n *    -  don't use AffineTransform for rescaling since it inverts\n *       images and strings\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.awt.BasicStroke;\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.FileDialog;\nimport java.awt.Font;\nimport java.awt.FontMetrics;\nimport java.awt.Graphics;\nimport java.awt.Graphics2D;\nimport java.awt.Image;\nimport java.awt.MediaTracker;\nimport java.awt.RenderingHints;\nimport java.awt.Toolkit;\n\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.awt.event.MouseEvent;\nimport java.awt.event.MouseListener;\nimport java.awt.event.MouseMotionListener;\nimport java.awt.event.KeyEvent;\nimport java.awt.event.KeyListener;\n\nimport java.awt.geom.Arc2D;\nimport java.awt.geom.Ellipse2D;\nimport java.awt.geom.GeneralPath;\nimport java.awt.geom.Line2D;\nimport java.awt.geom.Rectangle2D;\n\nimport java.awt.image.BufferedImage;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.net.URI;\nimport java.net.URISyntaxException;\n\nimport java.util.LinkedList;\nimport java.util.TreeSet;\nimport java.util.NoSuchElementException;\nimport javax.imageio.ImageIO;\n\nimport javax.swing.ImageIcon;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JMenuItem;\nimport javax.swing.KeyStroke;\n\n/**\n *  The {@code StdDraw} class provides static methods for creating drawings\n *  with your programs. It uses a simple graphics model that\n *  allows you to create drawings consisting of points, lines, squares,\n *  circles, and other geometric shapes in a window on your computer and\n *  to save the drawings to a file. Standard drawing also includes\n *  facilities for text, color, pictures, and animation, along with\n *  user interaction via the keyboard and mouse.\n *  <p>\n *  <b>Getting started.</b>\n *  To use this class, you must have {@code StdDraw.class} in your\n *  Java classpath. If you used our autoinstaller, you should be all set.\n *  Otherwise, either download\n *  <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  and add to your Java classpath or download\n *  <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdDraw.java\">StdDraw.java</a>\n *  and put a copy in your working directory.\n *  <p>\n *  Now, cut-and-paste the following short program into your editor:\n *  <pre>\n *   public class TestStdDraw {\n *       public static void main(String[] args) {\n *           StdDraw.setPenRadius(0.05);\n *           StdDraw.setPenColor(StdDraw.BLUE);\n *           StdDraw.point(0.5, 0.5);\n *           StdDraw.setPenColor(StdDraw.MAGENTA);\n *           StdDraw.line(0.2, 0.2, 0.8, 0.2);\n *       }\n *   }\n *  </pre>\n *  If you compile and execute the program, you should see a window\n *  appear with a thick magenta line and a blue point.\n *  This program illustrates the two main types of methods in standard\n *  drawing—methods that draw geometric shapes and methods that\n *  control drawing parameters.\n *  The methods {@code StdDraw.line()} and {@code StdDraw.point()}\n *  draw lines and points; the methods {@code StdDraw.setPenRadius()}\n *  and {@code StdDraw.setPenColor()} control the line thickness and color.\n *  <p>\n *  <b>Points and lines.</b>\n *  You can draw points and line segments with the following methods:\n *  <ul>\n *  <li> {@link #point(double x, double y)}\n *  <li> {@link #line(double x1, double y1, double x2, double y2)}\n *  </ul>\n *  <p>\n *  The <em>x</em>- and <em>y</em>-coordinates must be in the drawing area\n *  (between 0 and 1 and by default) or the points and lines will not be visible.\n *  <p>\n *  <b>Squares, circles, rectangles, and ellipses.</b>\n *  You can draw squares, circles, rectangles, and ellipses using\n *  the following methods:\n *  <ul>\n *  <li> {@link #circle(double x, double y, double radius)}\n *  <li> {@link #ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis)}\n *  <li> {@link #square(double x, double y, double halfLength)}\n *  <li> {@link #rectangle(double x, double y, double halfWidth, double halfHeight)}\n *  </ul>\n *  <p>\n *  All of these methods take as arguments the location and size of the shape.\n *  The location is always specified by the <em>x</em>- and <em>y</em>-coordinates\n *  of its <em>center</em>.\n *  The size of a circle is specified by its radius and the size of an ellipse is\n *  specified by the lengths of its semi-major and semi-minor axes.\n *  The size of a square or rectangle is specified by its half-width or half-height.\n *  The convention for drawing squares and rectangles is parallel to those for\n *  drawing circles and ellipses, but may be unexpected to the uninitiated.\n *  <p>\n *  The methods above trace outlines of the given shapes. The following methods\n *  draw filled versions:\n *  <ul>\n *  <li> {@link #filledCircle(double x, double y, double radius)}\n *  <li> {@link #filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis)}\n *  <li> {@link #filledSquare(double x, double y, double radius)}\n *  <li> {@link #filledRectangle(double x, double y, double halfWidth, double halfHeight)}\n *  </ul>\n *  <p>\n *  <b>Circular arcs.</b>\n *  You can draw circular arcs with the following method:\n *  <ul>\n *  <li> {@link #arc(double x, double y, double radius, double angle1, double angle2)}\n *  </ul>\n *  <p>\n *  The arc is from the circle centered at (<em>x</em>, <em>y</em>) of the specified radius.\n *  The arc extends from angle1 to angle2. By convention, the angles are\n *  <em>polar</em> (counterclockwise angle from the <em>x</em>-axis)\n *  and represented in degrees. For example, {@code StdDraw.arc(0.0, 0.0, 1.0, 0, 90)}\n *  draws the arc of the unit circle from 3 o'clock (0 degrees) to 12 o'clock (90 degrees).\n *  <p>\n *  <b>Polygons.</b>\n *  You can draw polygons with the following methods:\n *  <ul>\n *  <li> {@link #polygon(double[] x, double[] y)}\n *  <li> {@link #filledPolygon(double[] x, double[] y)}\n *  </ul>\n *  <p>\n *  The points in the polygon are ({@code x[i]}, {@code y[i]}).\n *  For example, the following code fragment draws a filled diamond\n *  with vertices (0.1, 0.2), (0.2, 0.3), (0.3, 0.2), and (0.2, 0.1):\n *  <pre>\n *   double[] x = { 0.1, 0.2, 0.3, 0.2 };\n *   double[] y = { 0.2, 0.3, 0.2, 0.1 };\n *   StdDraw.filledPolygon(x, y);\n *  </pre>\n *  <p>\n *  <b>Pen size.</b>\n *  The pen is circular, so that when you set the pen radius to <em>r</em>\n *  and draw a point, you get a circle of radius <em>r</em>. Also, lines are\n *  of thickness 2<em>r</em> and have rounded ends. The default pen radius\n *  is 0.002 and is not affected by coordinate scaling. This default pen\n *  radius is about 1/500 the width of the default canvas, so that if\n *  you draw 200 points equally spaced along a horizontal or vertical line,\n *  you will be able to see individual circles, but if you draw 250 such\n *  points, the result will look like a line.\n *  <ul>\n *  <li> {@link #setPenRadius(double radius)}\n *  </ul>\n *  <p>\n *  For example, {@code StdDraw.setPenRadius(0.01)} makes\n *  the thickness of the lines and the size of the points to be five times\n *  the 0.002 default.\n *  To draw points with the minimum possible radius (one pixel on typical\n *  displays), set the pen radius to 0.0.\n *  <p>\n *  <b>Pen color.</b>\n *  All geometric shapes (such as points, lines, and circles) are drawn using\n *  the current pen color. By default, it is black.\n *  You can change the pen color with the following methods:\n *  <ul>\n *  <li> {@link #setPenColor(int red, int green, int blue)}\n *  <li> {@link #setPenColor(Color color)}\n *  </ul>\n *  <p>\n *  The first method allows you to specify colors using the RGB color system.\n *  This <a href = \"http://johndyer.name/lab/colorpicker/\">color picker</a>\n *  is a convenient way to find a desired color.\n *  <p>\n *  The second method allows you to specify colors using the\n *  {@link Color} data type, which is defined in Java's {@link java.awt} package.\n *  Standard drawing defines a number of predefined colors including\n *  {@link #BLACK}, {@link #WHITE}, {@link #RED}, {@link #GREEN},\n *  and {@link #BLUE}.\n *  For example, {@code StdDraw.setPenColor(StdDraw.RED)} sets the\n *  pen color to red.\n *  <p>\n *  <b>Window title.</b>\n *  By default, the standard drawing window title is \"Standard Draw\".\n *  You can change the title with the following method:\n *  <ul>\n *  <li> {@link #setTitle(String windowTitle)}\n *  </ul>\n *  <p>\n *  This sets the standard drawing window title to the specified string.\n *  <p>\n *  <b>Canvas size.</b>\n *  By default, all drawing takes places in a 512-by-512 canvas.\n *  The canvas does not include the window title or window border.\n *  You can change the size of the canvas with the following method:\n *  <ul>\n *  <li> {@link #setCanvasSize(int width, int height)}\n *  </ul>\n *  <p>\n *  This sets the canvas size to be <em>width</em>-by-<em>height</em> pixels.\n *  It also clears the current drawing using the default background color (white).\n *  Ordinarily, this method is called only once, at the very beginning of a program.\n *  For example, {@code StdDraw.setCanvasSize(800, 800)}\n *  sets the canvas size to be 800-by-800 pixels.\n *  <p>\n *  <b>Canvas scale and coordinate system.</b>\n *  By default, all drawing takes places in the unit square, with (0, 0) at\n *  lower left and (1, 1) at upper right. You can change the default\n *  coordinate system with the following methods:\n *  <ul>\n *  <li> {@link #setXscale(double xmin, double xmax)}\n *  <li> {@link #setYscale(double ymin, double ymax)}\n *  <li> {@link #setScale(double min, double max)}\n *  </ul>\n *  <p>\n *  The arguments are the coordinates of the minimum and maximum\n *  <em>x</em>- or <em>y</em>-coordinates that will appear in the canvas.\n *  For example, if you  wish to use the default coordinate system but\n *  leave a small margin, you can call {@code StdDraw.setScale(-.05, 1.05)}.\n *  <p>\n *  These methods change the coordinate system for subsequent drawing\n *  commands; they do not affect previous drawings.\n *  These methods do not change the canvas size; so, if the <em>x</em>-\n *  and <em>y</em>-scales are different, squares will become rectangles\n *  and circles will become ellipses.\n *  <p>\n *  <b>Text.</b>\n *  You can use the following methods to annotate your drawings with text:\n *  <ul>\n *  <li> {@link #text(double x, double y, String text)}\n *  <li> {@link #text(double x, double y, String text, double degrees)}\n *  <li> {@link #textLeft(double x, double y, String text)}\n *  <li> {@link #textRight(double x, double y, String text)}\n *  </ul>\n *  <p>\n *  The first two methods write the specified text in the current font,\n *  centered at (<em>x</em>, <em>y</em>).\n *  The second method allows you to rotate the text.\n *  The last two methods either left- or right-align the text at (<em>x</em>, <em>y</em>).\n *  <p>\n *  The default font is a Sans Serif font with point size 16.\n *  You can use the following method to change the font:\n *  <ul>\n *  <li> {@link #setFont(Font font)}\n *  </ul>\n *  <p>\n *  To specify the font, you use the {@link Font} data type,\n *  which is defined in Java's {@link java.awt} package.\n *  This allows you to\n *  choose the face, size, and style of the font. For example, the following\n *  code fragment sets the font to Arial Bold, 60 point.\n *  The <code>import</code> statement allows you to refer to <code>Font</code>\n *  directly, without needing the fully qualified name <code>java.awt.Font</code>.\n *  <pre>\n *   import java.awt.Font;\n *   ...\n *   Font font = new Font(\"Arial\", Font.BOLD, 60);\n *   StdDraw.setFont(font);\n *   StdDraw.text(0.5, 0.5, \"Hello, World\");\n *  </pre>\n *  <p>\n *  <b>Images.</b>\n *  You can use the following methods to add images to your drawings:\n *  <ul>\n *  <li> {@link #picture(double x, double y, String filename)}\n *  <li> {@link #picture(double x, double y, String filename, double degrees)}\n *  <li> {@link #picture(double x, double y, String filename, double scaledWidth, double scaledHeight)}\n *  <li> {@link #picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees)}\n *  </ul>\n *  <p>\n *  These methods draw the specified image, centered at (<em>x</em>, <em>y</em>).\n *  The image must be in a supported file format (typically JPEG, PNG, GIF, TIFF, and BMP).\n *  The image will display at its native size, independent of the coordinate system.\n *  Optionally, you can rotate the image a specified number of degrees counterclockwise\n *  or rescale it to fit snugly inside a bounding box.\n *  <p>\n *  <b>Saving to a file.</b>\n *  You can save your image to a file using the <em>File → Save</em> menu option.\n *  You can also save a file programmatically using the following method:\n *  <ul>\n *  <li> {@link #save(String filename)}\n *  </ul>\n *  <p>\n *  You can save the drawing to a file in a supported file format\n *  (typically JPEG, PNG, GIF, TIFF, and BMP).\n *\n *  <p><b>File formats.</b>\n *  The {@code StdDraw} class supports reading and writing images to any of the\n *  file formats supported by {@link javax.imageio} (typically JPEG, PNG,\n *  GIF, TIFF, and BMP).\n *  The file extensions corresponding to JPEG, PNG, GIF, TIFF, and BMP,\n *  are {@code .jpg}, {@code .png}, {@code .gif}, {@code .tif},\n *  and {@code .bmp}, respectively.\n *  <p>\n *  We recommend using PNG for drawing that consist solely of geometric shapes\n *  and JPEG for drawings that contains pictures.\n *  The JPEG file format does not support transparent backgrounds.\n *\n *  <p>\n *  <b>Clearing the canvas.</b>\n *  To clear the entire drawing canvas, you can use the following methods:\n *  <ul>\n *  <li> {@link #clear()}\n *  <li> {@link #clear(Color color)}\n *  </ul>\n *  <p>\n *  The first method clears the canvas to the default background color (white);\n *  the second method allows you to specify the background color. For example,\n *  {@code StdDraw.clear(StdDraw.LIGHT_GRAY)} clears the canvas to a shade\n *  of gray. To make the background transparent,\n *  call {@code StdDraw.clear(StdDraw.TRANSPARENT)}.\n *\n *  <p>\n *  <b>Computer animations and double buffering.</b>\n *  Double buffering is one of the most powerful features of standard drawing,\n *  enabling computer animations.\n *  The following methods control the way in which objects are drawn:\n *  <ul>\n *  <li> {@link #enableDoubleBuffering()}\n *  <li> {@link #disableDoubleBuffering()}\n *  <li> {@link #show()}\n *  <li> {@link #pause(int t)}\n *  </ul>\n *  <p>\n *  By default, double buffering is disabled, which means that as soon as you\n *  call a drawing\n *  method—such as {@code point()} or {@code line()}—the\n *  results appear on the screen.\n *  <p>\n *  When double buffering is enabled by calling {@link #enableDoubleBuffering()},\n *  all drawing takes place on the <em>offscreen canvas</em>. The offscreen canvas\n *  is not displayed. Only when you call\n *  {@link #show()} does your drawing get copied from the offscreen canvas to\n *  the onscreen canvas, where it is displayed in the standard drawing window. You\n *  can think of double buffering as collecting all of the lines, points, shapes,\n *  and text that you tell it to draw, and then drawing them all\n *  <em>simultaneously</em>, upon request.\n *  <p>\n *  The most important use of double buffering is to produce computer\n *  animations, creating the illusion of motion by rapidly\n *  displaying static drawings. To produce an animation, repeat\n *  the following four steps:\n *  <ul>\n *  <li> Clear the offscreen canvas.\n *  <li> Draw objects on the offscreen canvas.\n *  <li> Copy the offscreen canvas to the onscreen canvas.\n *  <li> Wait for a short while.\n *  </ul>\n *  <p>\n *  The {@link #clear()}, {@link #show()}, and {@link #pause(int t)} methods\n *  support the first, third, and fourth of these steps, respectively.\n *  <p>\n *  For example, this code fragment animates two balls moving in a circle.\n *  <pre>\n *   StdDraw.setScale(-2.0, +2.0);\n *   StdDraw.enableDoubleBuffering();\n *\n *   for (double t = 0.0; true; t += 0.02) {\n *       double x = Math.sin(t);\n *       double y = Math.cos(t);\n *       StdDraw.clear();\n *       StdDraw.filledCircle(x, y, 0.1);\n *       StdDraw.filledCircle(-x, -y, 0.1);\n *       StdDraw.show();\n *       StdDraw.pause(20);\n *   }\n *  </pre>\n *  Without double buffering, the balls would flicker as they move.\n *  <p>\n *  <b>Keyboard and mouse inputs.</b>\n *  Standard drawing has very basic support for keyboard and mouse input.\n *  It is much less powerful than most user interface libraries provide, but also much simpler.\n *  You can use the following methods to intercept mouse events:\n *  <ul>\n *  <li> {@link #isMousePressed()}\n *  <li> {@link #mouseX()}\n *  <li> {@link #mouseY()}\n *  </ul>\n *  <p>\n *  The first method tells you whether a mouse button is currently being pressed.\n *  The last two methods tells you the <em>x</em>- and <em>y</em>-coordinates of the mouse's\n *  current position, using the same coordinate system as the canvas (the unit square, by default).\n *  You should use these methods in an animation loop that waits a short while before trying\n *  to poll the mouse for its current state.\n *  You can use the following methods to intercept keyboard events:\n *  <ul>\n *  <li> {@link #hasNextKeyTyped()}\n *  <li> {@link #nextKeyTyped()}\n *  <li> {@link #isKeyPressed(int keycode)}\n *  </ul>\n *  <p>\n *  If the user types lots of keys, they will be saved in a list until you process them.\n *  The first method tells you whether the user has typed a key (that your program has\n *  not yet processed).\n *  The second method returns the next key that the user typed (that your program has\n *  not yet processed) and removes it from the list of saved keystrokes.\n *  The third method tells you whether a key is currently being pressed.\n *  <p>\n *  <b>Accessing control parameters.</b>\n *  You can use the following methods to access the current pen color, pen radius,\n *  and font:\n *  <ul>\n *  <li> {@link #getPenColor()}\n *  <li> {@link #getBackgroundColor()}\n *  <li> {@link #getPenRadius()}\n *  <li> {@link #getFont()}\n *  </ul>\n *  <p>\n *  These methods are useful when you want to temporarily change a\n *  control parameter and, later, reset it back to its original value.\n *  <p>\n *  <b>Corner cases.</b>\n *  Here are some corner cases.\n *  <ul>\n *  <li> Drawing an object outside (or partly outside) the canvas is permitted.\n *       However, only the part of the object that appears inside the canvas\n *       will be visible.\n *  <li> Due to floating-point issues, an object drawn with an <em>x</em>- or\n *       <em>y</em>-coordinate that is way outside the canvas (such as the line segment\n *       from (0.5, –10^308) to (0.5, 10^308) may not be visible even in the\n *       part of the canvas where it should be.\n *  <li> Any method that is passed a {@code null} argument will throw an\n *       {@link IllegalArgumentException}.\n *  <li> Any method that is passed a {@link Double#NaN},\n *       {@link Double#POSITIVE_INFINITY}, or {@link Double#NEGATIVE_INFINITY}\n *       argument will throw an {@link IllegalArgumentException}.\n *  </ul>\n *  <p>\n *  <b>Performance tricks.</b>\n *  Standard drawing is capable of drawing large amounts of data.\n *  Here are a few tricks and tips:\n *  <ul>\n *  <li> Use <em>double buffering</em> for static drawing with a large\n *       number of objects.\n *       That is, call {@link #enableDoubleBuffering()} before\n *       the sequence of drawing commands and call {@link #show()} afterwards.\n *       Incrementally displaying a complex drawing while it is being\n *       created can be intolerably inefficient on many computer systems.\n *  <li> When drawing computer animations, call {@code show()}\n *       only once per frame, not after drawing each individual object.\n *  <li> If you call {@code picture()} multiple times with the same filename,\n *       Java will cache the image, so you do not incur the cost of reading\n *       from a file each time.\n *  </ul>\n *  <p>\n *  <b>Known bugs and issues.</b>\n *  <ul>\n *  <li> The {@code picture()} methods may not draw the portion of the image that is\n *       inside the canvas if the center point (<em>x</em>, <em>y</em>) is outside the\n *       canvas.\n *       This bug appears only on some systems.\n *  </ul>\n *  <p>\n *  <b>Reference.</b>\n *  For additional documentation,\n *  see <a href=\"https://introcs.cs.princeton.edu/15inout\">Section 1.5</a> of\n *  <em>Computer Science: An Interdisciplinary Approach</em>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdDraw implements ActionListener, MouseListener, MouseMotionListener, KeyListener {\n\n    /**\n     *  The color aqua (0, 255, 255).\n     */\n    public static final Color AQUA = new Color(0, 255, 255);\n\n    /**\n     *  The color black (0, 0, 0).\n     */\n    public static final Color BLACK = Color.BLACK;\n\n    /**\n     *  The color blue (0, 0, 255).\n     */\n    public static final Color BLUE = Color.BLUE;\n\n    /**\n     *  The color cyan (0, 255, 255).\n     */\n    public static final Color CYAN = Color.CYAN;\n\n    /**\n     *  The color fuscia (255, 0, 255).\n     */\n    public static final Color FUSCIA = new Color(255, 0, 255);\n\n    /**\n     *  The color dark gray (64, 64, 64).\n     */\n    public static final Color DARK_GRAY = Color.DARK_GRAY;\n\n    /**\n     *  The color gray (128, 128, 128).\n     */\n    public static final Color GRAY = Color.GRAY;\n\n    /**\n     *  The color green (0, 128, 0).\n     */\n    public static final Color GREEN = new Color(0, 128, 0);\n\n    /**\n     *  The color light gray (192, 192, 192).\n     */\n    public static final Color LIGHT_GRAY = Color.LIGHT_GRAY;\n\n    /**\n     *  The color lime (0, 255, 0).\n     */\n    public static final Color LIME = new Color(0, 255, 0);\n\n    /**\n     *  The color magenta (255, 0, 255).\n     */\n    public static final Color MAGENTA = Color.MAGENTA;\n\n    /**\n     *  The color maroon (128, 0, 0).\n     */\n    public static final Color MAROON = new Color(128, 0, 0);\n\n    /**\n     *  The color navy (0, 0, 128).\n     */\n    public static final Color NAVY = new Color(0, 0, 128);\n\n    /**\n     *  The color olive (128, 128, 0).\n     */\n    public static final Color OLIVE = new Color(128, 128, 0);\n\n    /**\n     *  The color orange (255, 200, 0).\n     */\n    public static final Color ORANGE = Color.ORANGE;\n\n    /**\n     *  The color pink (255, 175, 175).\n     */\n    public static final Color PINK = Color.PINK;\n\n    /**\n     *  The color purple (128, 0, 128).\n     */\n    public static final Color PURPLE = new Color(128, 0, 128);\n\n    /**\n     *  The color red (255, 0, 0).\n     */\n    public static final Color RED = Color.RED;\n\n    /**\n     *  The color silver (192, 192, 192).\n     */\n    public static final Color SILVER = new Color(192, 192, 192);\n\n    /**\n     *  The color teal (0, 128, 128).\n     */\n    public static final Color TEAL = new Color(0, 128, 128);\n\n    /**\n     *  The color white (255, 255, 255).\n     */\n    public static final Color WHITE = Color.WHITE;\n\n    /**\n     *  The color yellow (255, 255, 0).\n     */\n    public static final Color YELLOW = Color.YELLOW;\n\n    /**\n     *  A 100% transparent color, for a transparent background.\n     */\n    public static final Color TRANSPARENT = new Color(0, 0, 0, 0);\n\n    /**\n     * The shade of blue used in <em>Introduction to Programming in Java</em>.\n     * It is Pantone 300U. The RGB values are approximately (9, 90, 166).\n     */\n    public static final Color BOOK_BLUE = new Color(9, 90, 166);\n\n    /**\n     * The shade of light blue used in <em>Introduction to Programming in Java</em>.\n     * The RGB values are approximately (103, 198, 243).\n     */\n    public static final Color BOOK_LIGHT_BLUE = new Color(103, 198, 243);\n\n    /**\n     * The shade of red used in <em>Algorithms, 4th edition</em>.\n     * It is Pantone 1805U. The RGB values are approximately (150, 35, 31).\n     */\n    public static final Color BOOK_RED = new Color(150, 35, 31);\n\n    /**\n     * The shade of orange used in Princeton University's identity.\n     * It is PMS 158. The RGB values are approximately (245, 128, 37).\n     */\n    public static final Color PRINCETON_ORANGE = new Color(245, 128, 37);\n\n    // default colors\n    private static final Color DEFAULT_PEN_COLOR = BLACK;\n    private static final Color DEFAULT_BACKGROUND_COLOR = WHITE;\n\n    // current pen color\n    private static Color penColor = DEFAULT_PEN_COLOR;\n\n    // current background color\n    private static Color backgroundColor = DEFAULT_BACKGROUND_COLOR;\n\n    // default title of standard drawing window\n    private static final String DEFAULT_WINDOW_TITLE = \"Standard Draw\";\n\n    // current title of standard drawing window\n    private static String windowTitle = DEFAULT_WINDOW_TITLE;\n\n    // default canvas size is DEFAULT_SIZE-by-DEFAULT_SIZE\n    private static final int DEFAULT_SIZE = 512;\n    private static int width  = DEFAULT_SIZE;\n    private static int height = DEFAULT_SIZE;\n\n    // default pen radius\n    private static final double DEFAULT_PEN_RADIUS = 0.002;\n\n    // current pen radius\n    private static double penRadius = DEFAULT_PEN_RADIUS;\n\n    // show we draw immediately or wait until next show?\n    private static boolean defer = false;\n\n    // boundary of drawing canvas, 0% border\n    // private static final double BORDER = 0.05;\n    private static final double BORDER = 0.00;\n    private static final double DEFAULT_XMIN = 0.0;\n    private static final double DEFAULT_XMAX = 1.0;\n    private static final double DEFAULT_YMIN = 0.0;\n    private static final double DEFAULT_YMAX = 1.0;\n\n    private static double xmin = DEFAULT_XMIN;\n    private static double xmax = DEFAULT_XMAX;\n    private static double ymin = DEFAULT_YMIN;\n    private static double ymax = DEFAULT_YMAX;\n\n    // for synchronization\n    private static final Object MOUSE_LOCK = new Object();\n    private static final Object KEY_LOCK = new Object();\n\n    // default font\n    private static final Font DEFAULT_FONT = new Font(\"SansSerif\", Font.PLAIN, 16);\n\n    // current font\n    private static Font font = DEFAULT_FONT;\n\n    // double buffered graphics\n    private static BufferedImage offscreenImage, onscreenImage;\n    private static Graphics2D offscreen, onscreen;\n\n    // singleton for callbacks: avoids generation of extra .class files\n    private static StdDraw std = new StdDraw();\n\n    // the frame for drawing to the screen\n    private static JFrame frame;\n\n    // is the JFrame visible (upon calling draw())?\n    private static boolean isJFrameVisible = true;\n\n    // mouse state\n    private static boolean isMousePressed = false;\n    private static double mouseX = 0;\n    private static double mouseY = 0;\n\n    // queue of typed key characters\n    private static LinkedList<Character> keysTyped = new LinkedList<Character>();\n\n\n    // set of key codes currently pressed down\n    private static TreeSet<Integer> keysDown = new TreeSet<Integer>();\n\n    // singleton pattern: client can't instantiate\n    private StdDraw() { }\n\n\n    // static initializer\n    static {\n        initCanvas();\n        initGUI();\n    }\n\n    /**\n     * Makes the drawing window visible or invisible.\n     *\n     * @param  isVisible if {@code true}, makes the drawing window visible,\n     *         otherwise hides the drawing window.\n     */\n    public static void setVisible(boolean isVisible) {\n        isJFrameVisible = isVisible;\n        frame.setVisible(isVisible);\n    }\n\n    /**\n     * Sets the canvas (drawing area) to be 512-by-512 pixels.\n     * This also clears the current drawing using the default background\n     * color (white).\n     * Ordinarily, this method is called once, at the very beginning\n     * of a program.\n     */\n    public static void setCanvasSize() {\n        setCanvasSize(DEFAULT_SIZE, DEFAULT_SIZE);\n    }\n\n    /**\n     * Sets the canvas (drawing area) to be <em>width</em>-by-<em>height</em> pixels.\n     * This also clears the current drawing using the default background\n     * color (white).\n     * Ordinarily, this method is called once, at the very beginning\n     * of a program.\n     *\n     * @param  canvasWidth the width as a number of pixels\n     * @param  canvasHeight the height as a number of pixels\n     * @throws IllegalArgumentException unless both {@code canvasWidth} and\n     *         {@code canvasHeight} are positive\n     */\n    public static void setCanvasSize(int canvasWidth, int canvasHeight) {\n        if (canvasWidth <= 0) throw new IllegalArgumentException(\"width must be positive\");\n        if (canvasHeight <= 0) throw new IllegalArgumentException(\"height must be positive\");\n        width = canvasWidth;\n        height = canvasHeight;\n        initCanvas();\n        initGUI();\n    }\n\n    // initialize the drawing canvas\n    private static void initCanvas() {\n\n        // BufferedImage stuff\n        offscreenImage = new BufferedImage(2*width, 2*height, BufferedImage.TYPE_INT_ARGB);\n        onscreenImage  = new BufferedImage(2*width, 2*height, BufferedImage.TYPE_INT_ARGB);\n        offscreen = offscreenImage.createGraphics();\n        onscreen  = onscreenImage.createGraphics();\n        offscreen.scale(2.0, 2.0);  // since we made it 2x as big\n\n        // initialize drawing window\n        offscreen.setBackground(DEFAULT_BACKGROUND_COLOR);\n        offscreen.clearRect(0, 0, width, height);\n        onscreen.setBackground(DEFAULT_BACKGROUND_COLOR);\n        onscreen.clearRect(0, 0, 2*width, 2*height);\n\n     \t// set the pen color\n        offscreen.setColor(DEFAULT_PEN_COLOR);\n\n        // add antialiasing\n        RenderingHints hints = new RenderingHints(null);\n        hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\n        hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\n        offscreen.addRenderingHints(hints);\n    }\n\n    // initialize the GUI\n    private static void initGUI() {\n\n        // create the JFrame (if necessary)\n        if (frame == null) {\n            frame = new JFrame();\n            frame.addKeyListener(std);    // JLabel cannot get keyboard focus\n            frame.setFocusTraversalKeysEnabled(false);  // allow VK_TAB with isKeyPressed()\n            frame.setResizable(false);\n            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            // closes all windows\n            // frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);      // closes only current window\n            frame.setTitle(windowTitle);\n            frame.setJMenuBar(createMenuBar());\n        }\n\n        // create the ImageIcon\n        RetinaImageIcon icon = new RetinaImageIcon(onscreenImage);\n        JLabel draw = new JLabel(icon);\n        draw.addMouseListener(std);\n        draw.addMouseMotionListener(std);\n\n        // finsh up the JFrame\n        frame.setContentPane(draw);\n        frame.pack();\n        frame.requestFocusInWindow();\n        frame.setVisible(false);\n    }\n\n    // create the menu bar\n    private static JMenuBar createMenuBar() {\n        JMenuBar menuBar = new JMenuBar();\n        JMenu menu = new JMenu(\"File\");\n        menuBar.add(menu);\n        JMenuItem menuItem1 = new JMenuItem(\" Save...   \");\n        menuItem1.addActionListener(std);\n        // Java 11: use getMenuShortcutKeyMaskEx()\n        // Java 8:  use getMenuShortcutKeyMask()\n        menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,\n                                Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()));\n        menu.add(menuItem1);\n        return menuBar;\n    }\n\n    /**\n     * Closes the standard drawing window.\n     * This allows the client program to terminate instead of requiring\n     * the user to close the standard drawing window manually.\n     * Drawing after calling this method will restore the previous window state.\n     */\n    public static void close() {\n        frame.dispose();\n    }\n\n   /***************************************************************************\n    *  Input validation helper methods.\n    ***************************************************************************/\n\n    // throw an IllegalArgumentException if x is NaN or infinite\n    private static void validate(double x, String name) {\n        if (Double.isNaN(x)) throw new IllegalArgumentException(name + \" is NaN\");\n        if (Double.isInfinite(x)) throw new IllegalArgumentException(name + \" is infinite\");\n    }\n\n    // throw an IllegalArgumentException if s is null\n    private static void validateNonnegative(double x, String name) {\n        if (x < 0) throw new IllegalArgumentException(name + \" negative\");\n    }\n\n    // throw an IllegalArgumentException if s is null\n    private static void validateNotNull(Object x, String name) {\n        if (x == null) throw new IllegalArgumentException(name + \" is null\");\n    }\n\n\n   /***************************************************************************\n    *  Set the title of standard drawing window.\n    ***************************************************************************/\n\n    /**\n     * Sets the title of the standard drawing window to the specified string.\n     *\n     * @param  title the title\n     * @throws IllegalArgumentException if {@code title} is {@code null}\n     */\n    public static void setTitle(String title) {\n        validateNotNull(title, \"title\");\n        frame.setTitle(title);\n        windowTitle = title;\n    }\n\n   /***************************************************************************\n    *  User and screen coordinate systems.\n    ***************************************************************************/\n\n    /**\n     * Sets the <em>x</em>-scale to the default range (between 0.0 and 1.0).\n     */\n    public static void setXscale() {\n        setXscale(DEFAULT_XMIN, DEFAULT_XMAX);\n    }\n\n    /**\n     * Sets the <em>y</em>-scale to the default range (between 0.0 and 1.0).\n     */\n    public static void setYscale() {\n        setYscale(DEFAULT_YMIN, DEFAULT_YMAX);\n    }\n\n    /**\n     * Sets both the <em>x</em>-scale and <em>y</em>-scale to the default range\n     * (between 0.0 and 1.0).\n     */\n    public static void setScale() {\n        setXscale();\n        setYscale();\n    }\n\n    /**\n     * Sets the <em>x</em>-scale to the specified range.\n     *\n     * @param  min the minimum value of the <em>x</em>-scale\n     * @param  max the maximum value of the <em>x</em>-scale\n     * @throws IllegalArgumentException if {@code (max == min)}\n     * @throws IllegalArgumentException if either {@code min} or {@code max} is either NaN or infinite\n     */\n    public static void setXscale(double min, double max) {\n        validate(min, \"min\");\n        validate(max, \"max\");\n        double size = max - min;\n        if (size == 0.0) throw new IllegalArgumentException(\"the min and max are the same\");\n        synchronized (MOUSE_LOCK) {\n            xmin = min - BORDER * size;\n            xmax = max + BORDER * size;\n        }\n    }\n\n    /**\n     * Sets the <em>y</em>-scale to the specified range.\n     *\n     * @param  min the minimum value of the <em>y</em>-scale\n     * @param  max the maximum value of the <em>y</em>-scale\n     * @throws IllegalArgumentException if {@code (max == min)}\n     * @throws IllegalArgumentException if either {@code min} or {@code max} is either NaN or infinite\n     */\n    public static void setYscale(double min, double max) {\n        validate(min, \"min\");\n        validate(max, \"max\");\n        double size = max - min;\n        if (size == 0.0) throw new IllegalArgumentException(\"the min and max are the same\");\n        synchronized (MOUSE_LOCK) {\n            ymin = min - BORDER * size;\n            ymax = max + BORDER * size;\n        }\n    }\n\n    /**\n     * Sets both the <em>x</em>-scale and <em>y</em>-scale to the (same) specified range.\n     *\n     * @param  min the minimum value of the <em>x</em>- and <em>y</em>-scales\n     * @param  max the maximum value of the <em>x</em>- and <em>y</em>-scales\n     * @throws IllegalArgumentException if {@code (max == min)}\n     * @throws IllegalArgumentException if either {@code min} or {@code max} is either NaN or infinite\n     */\n    public static void setScale(double min, double max) {\n        validate(min, \"min\");\n        validate(max, \"max\");\n        double size = max - min;\n        if (size == 0.0) throw new IllegalArgumentException(\"the min and max are the same\");\n        synchronized (MOUSE_LOCK) {\n            xmin = min - BORDER * size;\n            xmax = max + BORDER * size;\n            ymin = min - BORDER * size;\n            ymax = max + BORDER * size;\n        }\n    }\n\n    // helper functions that scale from user coordinates to screen coordinates and back\n    private static double  scaleX(double x) { return width  * (x - xmin) / (xmax - xmin); }\n    private static double  scaleY(double y) { return height * (ymax - y) / (ymax - ymin); }\n    private static double factorX(double w) { return w * width  / Math.abs(xmax - xmin);  }\n    private static double factorY(double h) { return h * height / Math.abs(ymax - ymin);  }\n    private static double   userX(double x) { return xmin + x * (xmax - xmin) / width;    }\n    private static double   userY(double y) { return ymax - y * (ymax - ymin) / height;   }\n\n\n    /**\n     * Clears the screen using the default background color (white).\n     */\n    public static void clear() {\n        clear(DEFAULT_BACKGROUND_COLOR);\n    }\n\n    /**\n     * Clears the screen using the specified background color.\n     * To make the background transparent, use {@code StdDraw.TRANSPARENT}.\n     *\n     * @param color the color to make the background\n     * @throws IllegalArgumentException if {@code color} is {@code null}\n     */\n    public static void clear(Color color) {\n        validateNotNull(color, \"color\");\n\n        backgroundColor = color;\n\n        offscreen.setBackground(backgroundColor);\n        offscreen.clearRect(0, 0, width, height);\n        onscreen.setBackground(backgroundColor);\n        onscreen.clearRect(0, 0, 2*width, 2*height);\n\n        draw();\n    }\n\n    /**\n     * Returns the current pen radius.\n     *\n     * @return the current value of the pen radius\n     */\n    public static double getPenRadius() {\n        return penRadius;\n    }\n\n    /**\n     * Sets the pen size to the default size (0.002).\n     * The pen is circular, so that lines have rounded ends, and when you set the\n     * pen radius and draw a point, you get a circle of the specified radius.\n     * The pen radius is not affected by coordinate scaling.\n     */\n    public static void setPenRadius() {\n        setPenRadius(DEFAULT_PEN_RADIUS);\n    }\n\n    /**\n     * Sets the radius of the pen to the specified size.\n     * The pen is circular, so that lines have rounded ends, and when you set the\n     * pen radius and draw a point, you get a circle of the specified radius.\n     * The pen radius is not affected by coordinate scaling.\n     *\n     * @param  radius the radius of the pen\n     * @throws IllegalArgumentException if {@code radius} is negative, NaN, or infinite\n     */\n    public static void setPenRadius(double radius) {\n        validate(radius, \"pen radius\");\n        validateNonnegative(radius, \"pen radius\");\n\n        penRadius = radius;\n        float scaledPenRadius = (float) (radius * DEFAULT_SIZE);\n        BasicStroke stroke = new BasicStroke(scaledPenRadius, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);\n        // BasicStroke stroke = new BasicStroke(scaledPenRadius);\n        offscreen.setStroke(stroke);\n    }\n\n    /**\n     * Returns the current pen color.\n     *\n     * @return the current pen color\n     */\n    public static Color getPenColor() {\n        return penColor;\n    }\n\n    /**\n     * Returns the current background color.\n     *\n     * @return the current background color\n     */\n    public static Color getBackgroundColor() {\n        return backgroundColor;\n    }\n\n    /**\n     * Sets the pen color to the default color (black).\n     */\n    public static void setPenColor() {\n        setPenColor(DEFAULT_PEN_COLOR);\n    }\n\n    /**\n     * Sets the pen color to the specified color.\n     * <p>\n     * There are a number predefined pen colors, such as\n     * {@code StdDraw.BLACK}, {@code StdDraw.WHITE}, {@code StdDraw.RED},\n     * {@code StdDraw.GREEN}, and {@code StdDraw.BLUE}.\n     *\n     * @param color the color to make the pen\n     * @throws IllegalArgumentException if {@code color} is {@code null}\n     */\n    public static void setPenColor(Color color) {\n        validateNotNull(color, \"color\");\n        penColor = color;\n        offscreen.setColor(penColor);\n    }\n\n    /**\n     * Sets the pen color to the specified RGB color.\n     *\n     * @param  red the amount of red (between 0 and 255)\n     * @param  green the amount of green (between 0 and 255)\n     * @param  blue the amount of blue (between 0 and 255)\n     * @throws IllegalArgumentException if {@code red}, {@code green},\n     *         or {@code blue} is outside its prescribed range\n     */\n    public static void setPenColor(int red, int green, int blue) {\n        if (red   < 0 || red   >= 256) throw new IllegalArgumentException(\"red must be between 0 and 255\");\n        if (green < 0 || green >= 256) throw new IllegalArgumentException(\"green must be between 0 and 255\");\n        if (blue  < 0 || blue  >= 256) throw new IllegalArgumentException(\"blue must be between 0 and 255\");\n        setPenColor(new Color(red, green, blue));\n    }\n\n    /**\n     * Returns the current font.\n     *\n     * @return the current font\n     */\n    public static Font getFont() {\n        return font;\n    }\n\n    /**\n     * Sets the font to the default font (sans serif, 16 point).\n     */\n    public static void setFont() {\n        setFont(DEFAULT_FONT);\n    }\n\n    /**\n     * Sets the font to the specified value.\n     *\n     * @param font the font\n     * @throws IllegalArgumentException if {@code font} is {@code null}\n     */\n    public static void setFont(Font font) {\n        validateNotNull(font, \"font\");\n        StdDraw.font = font;\n    }\n\n\n   /***************************************************************************\n    *  Drawing geometric shapes.\n    ***************************************************************************/\n\n    /**\n     * Draws a line segment between (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>) and\n     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>).\n     *\n     * @param  x0 the <em>x</em>-coordinate of one endpoint\n     * @param  y0 the <em>y</em>-coordinate of one endpoint\n     * @param  x1 the <em>x</em>-coordinate of the other endpoint\n     * @param  y1 the <em>y</em>-coordinate of the other endpoint\n     * @throws IllegalArgumentException if any coordinate is either NaN or infinite\n     */\n    public static void line(double x0, double y0, double x1, double y1) {\n        validate(x0, \"x0\");\n        validate(y0, \"y0\");\n        validate(x1, \"x1\");\n        validate(y1, \"y1\");\n        offscreen.draw(new Line2D.Double(scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1)));\n        draw();\n    }\n\n    /**\n     * Draws one pixel at (<em>x</em>, <em>y</em>).\n     * This method is private because pixels depend on the display.\n     * To achieve the same effect, set the pen radius to 0 and call {@code point()}.\n     *\n     * @param  x the <em>x</em>-coordinate of the pixel\n     * @param  y the <em>y</em>-coordinate of the pixel\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    private static void pixel(double x, double y) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        offscreen.fillRect((int) Math.round(scaleX(x)), (int) Math.round(scaleY(y)), 1, 1);\n    }\n\n    /**\n     * Draws a point centered at (<em>x</em>, <em>y</em>).\n     * The point is a filled circle whose radius is equal to the pen radius.\n     * To draw a single-pixel point, first set the pen radius to 0.\n     *\n     * @param x the <em>x</em>-coordinate of the point\n     * @param y the <em>y</em>-coordinate of the point\n     * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite\n     */\n    public static void point(double x, double y) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double r = penRadius;\n        float scaledPenRadius = (float) (r * DEFAULT_SIZE);\n\n        // double ws = factorX(2*r);\n        // double hs = factorY(2*r);\n        // if (ws <= 1 && hs <= 1) pixel(x, y);\n        if (scaledPenRadius <= 1) pixel(x, y);\n        else offscreen.fill(new Ellipse2D.Double(xs - scaledPenRadius/2, ys - scaledPenRadius/2,\n                                                 scaledPenRadius, scaledPenRadius));\n        draw();\n    }\n\n    /**\n     * Draws a circle of the specified radius, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the circle\n     * @param  y the <em>y</em>-coordinate of the center of the circle\n     * @param  radius the radius of the circle\n     * @throws IllegalArgumentException if {@code radius} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void circle(double x, double y, double radius) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(radius, \"radius\");\n        validateNonnegative(radius, \"radius\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*radius);\n        double hs = factorY(2*radius);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled circle of the specified radius, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the circle\n     * @param  y the <em>y</em>-coordinate of the center of the circle\n     * @param  radius the radius of the circle\n     * @throws IllegalArgumentException if {@code radius} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void filledCircle(double x, double y, double radius) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(radius, \"radius\");\n        validateNonnegative(radius, \"radius\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*radius);\n        double hs = factorY(2*radius);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n\n    /**\n     * Draws an ellipse with the specified semimajor and semiminor axes,\n     * centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the ellipse\n     * @param  y the <em>y</em>-coordinate of the center of the ellipse\n     * @param  semiMajorAxis is the semimajor axis of the ellipse\n     * @param  semiMinorAxis is the semiminor axis of the ellipse\n     * @throws IllegalArgumentException if either {@code semiMajorAxis}\n     *         or {@code semiMinorAxis} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(semiMajorAxis, \"semimajor axis\");\n        validate(semiMinorAxis, \"semiminor axis\");\n        validateNonnegative(semiMajorAxis, \"semimajor axis\");\n        validateNonnegative(semiMinorAxis, \"semiminor axis\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*semiMajorAxis);\n        double hs = factorY(2*semiMinorAxis);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled ellipse with the specified semimajor and semiminor axes,\n     * centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the ellipse\n     * @param  y the <em>y</em>-coordinate of the center of the ellipse\n     * @param  semiMajorAxis is the semimajor axis of the ellipse\n     * @param  semiMinorAxis is the semiminor axis of the ellipse\n     * @throws IllegalArgumentException if either {@code semiMajorAxis}\n     *         or {@code semiMinorAxis} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(semiMajorAxis, \"semimajor axis\");\n        validate(semiMinorAxis, \"semiminor axis\");\n        validateNonnegative(semiMajorAxis, \"semimajor axis\");\n        validateNonnegative(semiMinorAxis, \"semiminor axis\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*semiMajorAxis);\n        double hs = factorY(2*semiMinorAxis);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n\n    /**\n     * Draws a circular arc of the specified radius,\n     * centered at (<em>x</em>, <em>y</em>), from angle1 to angle2 (in degrees).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the circle\n     * @param  y the <em>y</em>-coordinate of the center of the circle\n     * @param  radius the radius of the circle\n     * @param  angle1 the starting angle. 0 would mean an arc beginning at 3 o'clock.\n     * @param  angle2 the angle at the end of the arc. For example, if\n     *         you want a 90 degree arc, then angle2 should be angle1 + 90.\n     * @throws IllegalArgumentException if {@code radius} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void arc(double x, double y, double radius, double angle1, double angle2) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(radius, \"arc radius\");\n        validate(angle1, \"angle1\");\n        validate(angle2, \"angle2\");\n        validateNonnegative(radius, \"arc radius\");\n\n        while (angle2 < angle1) angle2 += 360;\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*radius);\n        double hs = factorY(2*radius);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Arc2D.Double(xs - ws/2, ys - hs/2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN));\n        draw();\n    }\n\n    /**\n     * Draws a square of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the square\n     * @param  y the <em>y</em>-coordinate of the center of the square\n     * @param  halfLength one half the length of any side of the square\n     * @throws IllegalArgumentException if {@code halfLength} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void square(double x, double y, double halfLength) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfLength, \"halfLength\");\n        validateNonnegative(halfLength, \"half length\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfLength);\n        double hs = factorY(2*halfLength);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled square of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the square\n     * @param  y the <em>y</em>-coordinate of the center of the square\n     * @param  halfLength one half the length of any side of the square\n     * @throws IllegalArgumentException if {@code halfLength} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void filledSquare(double x, double y, double halfLength) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfLength, \"halfLength\");\n        validateNonnegative(halfLength, \"half length\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfLength);\n        double hs = factorY(2*halfLength);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n\n    /**\n     * Draws a rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the rectangle\n     * @param  y the <em>y</em>-coordinate of the center of the rectangle\n     * @param  halfWidth one half the width of the rectangle\n     * @param  halfHeight one half the height of the rectangle\n     * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void rectangle(double x, double y, double halfWidth, double halfHeight) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfWidth, \"halfWidth\");\n        validate(halfHeight, \"halfHeight\");\n        validateNonnegative(halfWidth, \"half width\");\n        validateNonnegative(halfHeight, \"half height\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfWidth);\n        double hs = factorY(2*halfHeight);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n    /**\n     * Draws a filled rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the center of the rectangle\n     * @param  y the <em>y</em>-coordinate of the center of the rectangle\n     * @param  halfWidth one half the width of the rectangle\n     * @param  halfHeight one half the height of the rectangle\n     * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative\n     * @throws IllegalArgumentException if any argument is either NaN or infinite\n     */\n    public static void filledRectangle(double x, double y, double halfWidth, double halfHeight) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(halfWidth, \"halfWidth\");\n        validate(halfHeight, \"halfHeight\");\n        validateNonnegative(halfWidth, \"half width\");\n        validateNonnegative(halfHeight, \"half height\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(2*halfWidth);\n        double hs = factorY(2*halfHeight);\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));\n        draw();\n    }\n\n\n    /**\n     * Draws a polygon with the vertices\n     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),\n     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,\n     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).\n     *\n     * @param  x an array of all the <em>x</em>-coordinates of the polygon\n     * @param  y an array of all the <em>y</em>-coordinates of the polygon\n     * @throws IllegalArgumentException unless {@code x[]} and {@code y[]}\n     *         are of the same length\n     * @throws IllegalArgumentException if any coordinate is either NaN or infinite\n     * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null}\n     */\n    public static void polygon(double[] x, double[] y) {\n        validateNotNull(x, \"x-coordinate array\");\n        validateNotNull(y, \"y-coordinate array\");\n        for (int i = 0; i < x.length; i++) validate(x[i], \"x[\" + i + \"]\");\n        for (int i = 0; i < y.length; i++) validate(y[i], \"y[\" + i + \"]\");\n\n        int n1 = x.length;\n        int n2 = y.length;\n        if (n1 != n2) throw new IllegalArgumentException(\"arrays must be of the same length\");\n        int n = n1;\n        if (n == 0) return;\n\n        GeneralPath path = new GeneralPath();\n        path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0]));\n        for (int i = 0; i < n; i++)\n            path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i]));\n        path.closePath();\n        offscreen.draw(path);\n        draw();\n    }\n\n    /**\n     * Draws a filled polygon with the vertices\n     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),\n     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,\n     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).\n     *\n     * @param  x an array of all the <em>x</em>-coordinates of the polygon\n     * @param  y an array of all the <em>y</em>-coordinates of the polygon\n     * @throws IllegalArgumentException unless {@code x[]} and {@code y[]}\n     *         are of the same length\n     * @throws IllegalArgumentException if any coordinate is either NaN or infinite\n     * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null}\n     */\n    public static void filledPolygon(double[] x, double[] y) {\n        validateNotNull(x, \"x-coordinate array\");\n        validateNotNull(y, \"y-coordinate array\");\n        for (int i = 0; i < x.length; i++) validate(x[i], \"x[\" + i + \"]\");\n        for (int i = 0; i < y.length; i++) validate(y[i], \"y[\" + i + \"]\");\n\n        int n1 = x.length;\n        int n2 = y.length;\n        if (n1 != n2) throw new IllegalArgumentException(\"arrays must be of the same length\");\n        int n = n1;\n        if (n == 0) return;\n\n        GeneralPath path = new GeneralPath();\n        path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0]));\n        for (int i = 0; i < n; i++)\n            path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i]));\n        path.closePath();\n        offscreen.fill(path);\n        draw();\n    }\n\n\n   /***************************************************************************\n    *  Drawing images.\n    ***************************************************************************/\n    // get an image from the given filename\n    private static Image getImage(String filename) {\n        if (filename == null) throw new IllegalArgumentException();\n\n        // to read from file\n        ImageIcon icon = new ImageIcon(filename);\n\n        // try to read from URL\n        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {\n            try {\n                URI uri = new URI(filename);\n                if (uri.isAbsolute()) {\n                    URL url = uri.toURL();\n                    icon = new ImageIcon(url);\n                }\n            }\n            catch (MalformedURLException | URISyntaxException e) {\n                /* not a url */\n            }\n        }\n\n        // in case file is inside a .jar (classpath relative to StdDraw)\n        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {\n            URL url = StdDraw.class.getResource(filename);\n            if (url != null)\n                icon = new ImageIcon(url);\n        }\n\n        // in case file is inside a .jar (classpath relative to root of jar)\n        if (icon.getImageLoadStatus() != MediaTracker.COMPLETE) {\n            URL url = StdDraw.class.getResource(\"/\" + filename);\n            if (url == null) throw new IllegalArgumentException(\"could not read image: '\" + filename + \"'\");\n            icon = new ImageIcon(url);\n        }\n\n        return icon.getImage();\n    }\n\n   /***************************************************************************\n    * [Summer 2016] Should we update to use ImageIO instead of ImageIcon()?\n    *               Seems to have some issues loading images on some systems\n    *               and slows things down on other systems.\n    *               especially if you don't call ImageIO.setUseCache(false)\n    *               One advantage is that it returns a BufferedImage.\n    ***************************************************************************/\n/*\n    private static BufferedImage getImage(String filename) {\n        if (filename == null) throw new IllegalArgumentException();\n\n        // from a file or URL\n        try {\n            URL url = new URL(filename);\n            BufferedImage image = ImageIO.read(url);\n            return image;\n        }\n        catch (IOException e) {\n            // ignore\n        }\n\n        // in case file is inside a .jar (classpath relative to StdDraw)\n        try {\n            URL url = StdDraw.class.getResource(filename);\n            BufferedImage image = ImageIO.read(url);\n            return image;\n        }\n        catch (IOException e) {\n            // ignore\n        }\n\n        // in case file is inside a .jar (classpath relative to root of jar)\n        try {\n            URL url = StdDraw.class.getResource(\"/\" + filename);\n            BufferedImage image = ImageIO.read(url);\n            return image;\n        }\n        catch (IOException e) {\n            // ignore\n        }\n        throw new IllegalArgumentException(\"image \" + filename + \" not found\");\n    }\n*/\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>).\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     * As an optimization, the picture is cached, so there is no performance\n     * penalty for redrawing the same image multiple times (e.g., in an animation).\n     * However, if you change the picture file after drawing it, subsequent\n     * calls will draw the original picture.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @throws IllegalArgumentException if the image filename is invalid\n     * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite\n     */\n    public static void picture(double x, double y, String filename) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(filename, \"filename\");\n\n        // BufferedImage image = getImage(filename);\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        // int ws = image.getWidth();    // can call only if image is a BufferedImage\n        // int hs = image.getHeight();\n        int ws = image.getWidth(null);\n        int hs = image.getHeight(null);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n\n        offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null);\n        draw();\n    }\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>),\n     * rotated given number of degrees.\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @param  degrees is the number of degrees to rotate counterclockwise\n     * @throws IllegalArgumentException if the image filename is invalid\n     * @throws IllegalArgumentException if {@code x}, {@code y}, {@code degrees} is NaN or infinite\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public static void picture(double x, double y, String filename, double degrees) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(degrees, \"degrees\");\n        validateNotNull(filename, \"filename\");\n\n        // BufferedImage image = getImage(filename);\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        // int ws = image.getWidth();    // can call only if image is a BufferedImage\n        // int hs = image.getHeight();\n        int ws = image.getWidth(null);\n        int hs = image.getHeight(null);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n\n        offscreen.rotate(Math.toRadians(-degrees), xs, ys);\n        offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null);\n        offscreen.rotate(Math.toRadians(+degrees), xs, ys);\n\n        draw();\n    }\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>),\n     * rescaled to the specified bounding box.\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @param  scaledWidth the width of the scaled image (in screen coordinates)\n     * @param  scaledHeight the height of the scaled image (in screen coordinates)\n     * @throws IllegalArgumentException if either {@code scaledWidth}\n     *         or {@code scaledHeight} is negative\n     * @throws IllegalArgumentException if the image filename is invalid\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     */\n    public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(scaledWidth, \"scaled width\");\n        validate(scaledHeight, \"scaled height\");\n        validateNotNull(filename, \"filename\");\n        validateNonnegative(scaledWidth, \"scaled width\");\n        validateNonnegative(scaledHeight, \"scaled height\");\n\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(scaledWidth);\n        double hs = factorY(scaledHeight);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n        else {\n            offscreen.drawImage(image, (int) Math.round(xs - ws/2.0),\n                                       (int) Math.round(ys - hs/2.0),\n                                       (int) Math.round(ws),\n                                       (int) Math.round(hs), null);\n        }\n        draw();\n    }\n\n\n    /**\n     * Draws the specified image centered at (<em>x</em>, <em>y</em>), rotated\n     * given number of degrees, and rescaled to the specified bounding box.\n     * The supported image formats are typically JPEG, PNG, GIF, TIFF, and BMP.\n     *\n     * @param  x the center <em>x</em>-coordinate of the image\n     * @param  y the center <em>y</em>-coordinate of the image\n     * @param  filename the name of the image/picture, e.g., \"ball.gif\"\n     * @param  scaledWidth the width of the scaled image (in screen coordinates)\n     * @param  scaledHeight the height of the scaled image (in screen coordinates)\n     * @param  degrees is the number of degrees to rotate counterclockwise\n     * @throws IllegalArgumentException if either {@code scaledWidth}\n     *         or {@code scaledHeight} is negative\n     * @throws IllegalArgumentException if the image filename is invalid\n     */\n    public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(scaledWidth, \"scaled width\");\n        validate(scaledHeight, \"scaled height\");\n        validate(degrees, \"degrees\");\n        validateNotNull(filename, \"filename\");\n        validateNonnegative(scaledWidth, \"scaled width\");\n        validateNonnegative(scaledHeight, \"scaled height\");\n\n        Image image = getImage(filename);\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        double ws = factorX(scaledWidth);\n        double hs = factorY(scaledHeight);\n        if (ws < 0 || hs < 0) throw new IllegalArgumentException(\"image \" + filename + \" is corrupt\");\n        if (ws <= 1 && hs <= 1) pixel(x, y);\n\n        offscreen.rotate(Math.toRadians(-degrees), xs, ys);\n        offscreen.drawImage(image, (int) Math.round(xs - ws/2.0),\n                                   (int) Math.round(ys - hs/2.0),\n                                   (int) Math.round(ws),\n                                   (int) Math.round(hs), null);\n        offscreen.rotate(Math.toRadians(+degrees), xs, ys);\n\n        draw();\n    }\n\n   /***************************************************************************\n    *  Drawing text.\n    ***************************************************************************/\n\n    /**\n     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the center <em>x</em>-coordinate of the text\n     * @param  y the center <em>y</em>-coordinate of the text\n     * @param  text the text to write\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    public static void text(double x, double y, String text) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(text, \"text\");\n\n        offscreen.setFont(font);\n        FontMetrics metrics = offscreen.getFontMetrics();\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int ws = metrics.stringWidth(text);\n        int hs = metrics.getDescent();\n        offscreen.drawString(text, (float) (xs - ws/2.0), (float) (ys + hs));\n        draw();\n    }\n\n    /**\n     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>) and\n     * rotated by the specified number of degrees.\n     * @param  x the center <em>x</em>-coordinate of the text\n     * @param  y the center <em>y</em>-coordinate of the text\n     * @param  text the text to write\n     * @param  degrees is the number of degrees to rotate counterclockwise\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x}, {@code y}, or {@code degrees} is either NaN or infinite\n     */\n    public static void text(double x, double y, String text, double degrees) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validate(degrees, \"degrees\");\n        validateNotNull(text, \"text\");\n\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        offscreen.rotate(Math.toRadians(-degrees), xs, ys);\n        text(x, y, text);\n        offscreen.rotate(Math.toRadians(+degrees), xs, ys);\n    }\n\n\n    /**\n     * Writes the given text string in the current font, left-aligned at (<em>x</em>, <em>y</em>).\n     * @param  x the <em>x</em>-coordinate of the text\n     * @param  y the <em>y</em>-coordinate of the text\n     * @param  text the text\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    public static void textLeft(double x, double y, String text) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(text, \"text\");\n\n        offscreen.setFont(font);\n        FontMetrics metrics = offscreen.getFontMetrics();\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int hs = metrics.getDescent();\n        offscreen.drawString(text, (float) xs, (float) (ys + hs));\n        draw();\n    }\n\n    /**\n     * Writes the given text string in the current font, right-aligned at (<em>x</em>, <em>y</em>).\n     *\n     * @param  x the <em>x</em>-coordinate of the text\n     * @param  y the <em>y</em>-coordinate of the text\n     * @param  text the text to write\n     * @throws IllegalArgumentException if {@code text} is {@code null}\n     * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite\n     */\n    public static void textRight(double x, double y, String text) {\n        validate(x, \"x\");\n        validate(y, \"y\");\n        validateNotNull(text, \"text\");\n\n        offscreen.setFont(font);\n        FontMetrics metrics = offscreen.getFontMetrics();\n        double xs = scaleX(x);\n        double ys = scaleY(y);\n        int ws = metrics.stringWidth(text);\n        int hs = metrics.getDescent();\n        offscreen.drawString(text, (float) (xs - ws), (float) (ys + hs));\n        draw();\n    }\n\n\n    /**\n     * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds\n     * and enables double buffering.\n     * @param t number of milliseconds\n     * @throws IllegalArgumentException if {@code t} is negative\n     * @deprecated replaced by {@link #enableDoubleBuffering()}, {@link #show()}, and {@link #pause(int t)}\n     */\n    @Deprecated\n    public static void show(int t) {\n        validateNonnegative(t, \"t\");\n        show();\n        pause(t);\n        enableDoubleBuffering();\n    }\n\n    /**\n     * Pauses for t milliseconds. This method is intended to support computer animations.\n     * @param t number of milliseconds\n     * @throws IllegalArgumentException if {@code t} is negative\n     */\n    public static void pause(int t) {\n        validateNonnegative(t, \"t\");\n        try {\n            Thread.sleep(t);\n        }\n        catch (InterruptedException e) {\n            System.out.println(\"Error sleeping\");\n        }\n    }\n\n    /**\n     * Copies offscreen buffer to onscreen buffer. There is no reason to call\n     * this method unless double buffering is enabled.\n     */\n    public static void show() {\n        onscreen.drawImage(offscreenImage, 0, 0, null);\n\n        // make frame visible upon first call to show()\n        if (frame.isVisible() != isJFrameVisible) {\n            frame.setVisible(isJFrameVisible);\n        }\n\n        frame.repaint();\n    }\n\n    // draw onscreen if defer is false\n    private static void draw() {\n        if (!defer) show();\n    }\n\n    /**\n     * Enables double buffering. All subsequent calls to\n     * drawing methods such as {@code line()}, {@code circle()},\n     * and {@code square()} will be deferred until the next call\n     * to show(). Useful for animations.\n     */\n    public static void enableDoubleBuffering() {\n        defer = true;\n    }\n\n    /**\n     * Disables double buffering. All subsequent calls to\n     * drawing methods such as {@code line()}, {@code circle()},\n     * and {@code square()} will be displayed on screen when called.\n     * This is the default.\n     */\n    public static void disableDoubleBuffering() {\n        defer = false;\n    }\n\n\n   /***************************************************************************\n    *  Save drawing to a file.\n    ***************************************************************************/\n\n    /**\n     * Saves the drawing to a file in a supported file format\n     * (typically JPEG, PNG, GIF, TIFF, and BMP).\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     *\n     * @param  filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     * @throws IllegalArgumentException if {@code filename} has invalid filetype extension\n     * @throws IllegalArgumentException if cannot write the file {@code filename}\n     */\n    public static void save(String filename) {\n        validateNotNull(filename, \"filename\");\n        if (filename.length() == 0) {\n            throw new IllegalArgumentException(\"argument to save() is the empty string\");\n        }\n\n        File file = new File(filename);\n        String suffix = filename.substring(filename.lastIndexOf('.') + 1);\n        if (!filename.contains(\".\") || suffix.length() == 0) {\n            throw new IllegalArgumentException(\"The filename '\" + filename + \"' has no filetype extension, such as .jpg or .png\");\n        }\n\n        try {\n            // if the file format supports transparency (such as PNG or GIF)\n            if (ImageIO.write(onscreenImage, suffix, file)) return;\n\n            // if the file format does not support transparency (such as JPEG or BMP)\n            BufferedImage saveImage = new BufferedImage(2*width, 2*height, BufferedImage.TYPE_INT_RGB);\n            saveImage.createGraphics().drawImage(onscreenImage, 0, 0, Color.WHITE, null);\n            if (ImageIO.write(saveImage, suffix, file)) return;\n\n            // failed to save the file; probably wrong format\n            throw new IllegalArgumentException(\"The filetype '\" + suffix + \"' is not supported\");\n        }\n        catch (IOException e) {\n            throw new IllegalArgumentException(\"could not write file '\" + filename + \"'\", e);\n        }\n    }\n\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void actionPerformed(ActionEvent event) {\n        FileDialog chooser = new FileDialog(StdDraw.frame, \"Use a .png or .jpg extension\", FileDialog.SAVE);\n        chooser.setVisible(true);\n        String selectedDirectory = chooser.getDirectory();\n        String selectedFilename = chooser.getFile();\n        if (selectedDirectory != null && selectedFilename != null) {\n            try {\n                StdDraw.save(selectedDirectory + selectedFilename);\n            }\n            catch (IllegalArgumentException e) {\n                System.err.println(e.getMessage());\n            }\n        }\n    }\n\n\n   /***************************************************************************\n    *  Mouse interactions.\n    ***************************************************************************/\n\n    /**\n     * Returns true if the mouse is being pressed.\n     *\n     * @return {@code true} if the mouse is being pressed; {@code false} otherwise\n     */\n    public static boolean isMousePressed() {\n        synchronized (MOUSE_LOCK) {\n            return isMousePressed;\n        }\n    }\n\n    /**\n     * Returns true if the mouse is being pressed.\n     *\n     * @return {@code true} if the mouse is being pressed; {@code false} otherwise\n     * @deprecated replaced by {@link #isMousePressed()}\n     */\n    @Deprecated\n    public static boolean mousePressed() {\n        synchronized (MOUSE_LOCK) {\n            return isMousePressed;\n        }\n    }\n\n    /**\n     * Returns the <em>x</em>-coordinate of the mouse.\n     *\n     * @return the <em>x</em>-coordinate of the mouse\n     */\n    public static double mouseX() {\n        synchronized (MOUSE_LOCK) {\n            return mouseX;\n        }\n    }\n\n    /**\n     * Returns the <em>y</em>-coordinate of the mouse.\n     *\n     * @return <em>y</em>-coordinate of the mouse\n     */\n    public static double mouseY() {\n        synchronized (MOUSE_LOCK) {\n            return mouseY;\n        }\n    }\n\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseClicked(MouseEvent event) {\n        // this body is intentionally left empty\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseEntered(MouseEvent event) {\n        // this body is intentionally left empty\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseExited(MouseEvent event) {\n        // this body is intentionally left empty\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mousePressed(MouseEvent event) {\n        synchronized (MOUSE_LOCK) {\n            mouseX = StdDraw.userX(event.getX());\n            mouseY = StdDraw.userY(event.getY());\n            isMousePressed = true;\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseReleased(MouseEvent event) {\n        synchronized (MOUSE_LOCK) {\n            isMousePressed = false;\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseDragged(MouseEvent event)  {\n        synchronized (MOUSE_LOCK) {\n            mouseX = StdDraw.userX(event.getX());\n            mouseY = StdDraw.userY(event.getY());\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void mouseMoved(MouseEvent event) {\n        synchronized (MOUSE_LOCK) {\n            mouseX = StdDraw.userX(event.getX());\n            mouseY = StdDraw.userY(event.getY());\n        }\n    }\n\n\n   /***************************************************************************\n    *  Keyboard interactions.\n    ***************************************************************************/\n\n    /**\n     * Returns true if the user has typed a key (that has not yet been processed).\n     *\n     * @return {@code true} if the user has typed a key (that has not yet been processed\n     *         by {@link #nextKeyTyped()}; {@code false} otherwise\n     */\n    public static boolean hasNextKeyTyped() {\n        synchronized (KEY_LOCK) {\n            return !keysTyped.isEmpty();\n        }\n    }\n\n    /**\n     * Returns the next key that was typed by the user (that your program has not already processed).\n     * This method should be preceded by a call to {@link #hasNextKeyTyped()} to ensure\n     * that there is a next key to process.\n     * This method returns a Unicode character corresponding to the key\n     * typed (such as {@code 'a'} or {@code 'A'}).\n     * It cannot identify action keys (such as F1 and arrow keys)\n     * or modifier keys (such as control).\n     *\n     * @return the next key typed by the user (that your program has not already processed).\n     * @throws NoSuchElementException if there is no remaining key\n     */\n    public static char nextKeyTyped() {\n        synchronized (KEY_LOCK) {\n            if (keysTyped.isEmpty()) {\n                throw new NoSuchElementException(\"your program has already processed all keystrokes\");\n            }\n            return keysTyped.remove(keysTyped.size() - 1);\n            // return keysTyped.removeLast();\n        }\n    }\n\n    /**\n     * Returns true if the given key is being pressed.\n     * <p>\n     * This method takes the keycode (corresponding to a physical key)\n    *  as an argument. It can handle action keys\n     * (such as F1 and arrow keys) and modifier keys (such as shift and control).\n     * See {@link KeyEvent} for a description of key codes.\n     *\n     * @param  keycode the key to check if it is being pressed\n     * @return {@code true} if {@code keycode} is currently being pressed;\n     *         {@code false} otherwise\n     */\n    public static boolean isKeyPressed(int keycode) {\n        synchronized (KEY_LOCK) {\n            return keysDown.contains(keycode);\n        }\n    }\n\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void keyTyped(KeyEvent event) {\n        synchronized (KEY_LOCK) {\n            keysTyped.addFirst(event.getKeyChar());\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void keyPressed(KeyEvent event) {\n        synchronized (KEY_LOCK) {\n            keysDown.add(event.getKeyCode());\n        }\n    }\n\n    /**\n     * This method cannot be called directly.\n     */\n    @Override\n    public void keyReleased(KeyEvent event) {\n        synchronized (KEY_LOCK) {\n            keysDown.remove(event.getKeyCode());\n        }\n    }\n\n\n   /***************************************************************************\n    *  For improved resolution on Mac Retina displays.\n    ***************************************************************************/\n\n    private static class RetinaImageIcon extends ImageIcon {\n\n        public RetinaImageIcon(Image image) {\n            super(image);\n        }\n\n        public int getIconWidth() {\n            return super.getIconWidth() / 2;\n        }\n\n        /**\n         * Returns the height of the icon.\n         *\n         * @return the height in pixels of this icon\n         */\n        public int getIconHeight() {\n            return super.getIconHeight() / 2;\n        }\n\n        public synchronized void paintIcon(Component c, Graphics g, int x, int y) {\n            Graphics2D g2 = (Graphics2D) g.create();\n            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);\n            g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);\n            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);\n            g2.scale(0.5, 0.5);\n            super.paintIcon(c, g2, x * 2, y * 2);\n            g2.dispose();\n        }\n    }\n\n\n    /**\n     * Test client.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        StdDraw.square(0.2, 0.8, 0.1);\n        StdDraw.filledSquare(0.8, 0.8, 0.2);\n        StdDraw.circle(0.8, 0.2, 0.2);\n\n        StdDraw.setPenColor(StdDraw.BOOK_RED);\n        StdDraw.setPenRadius(0.02);\n        StdDraw.arc(0.8, 0.2, 0.1, 200, 45);\n\n        // draw a blue diamond\n        StdDraw.setPenRadius();\n        StdDraw.setPenColor(StdDraw.BOOK_BLUE);\n        double[] x = { 0.1, 0.2, 0.3, 0.2 };\n        double[] y = { 0.2, 0.3, 0.2, 0.1 };\n        StdDraw.filledPolygon(x, y);\n\n        // text\n        StdDraw.setPenColor(StdDraw.BLACK);\n        StdDraw.text(0.2, 0.5, \"black text\");\n        StdDraw.setPenColor(StdDraw.WHITE);\n        StdDraw.text(0.8, 0.8, \"white text\");\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdIn.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdIn.java\n *  Execution:    java StdIn   (interactive test of basic functionality)\n *  Dependencies: none\n *\n *  Reads in data of various types from standard input.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.ArrayList;\nimport java.util.InputMismatchException;\nimport java.util.Locale;\nimport java.util.NoSuchElementException;\nimport java.util.Scanner;\nimport java.util.regex.Pattern;\n\n/**\n *  The {@code StdIn} class provides static methods for reading strings\n *  and numbers from standard input.\n *  These functions fall into one of four categories:\n *  <ul>\n *  <li>those for reading individual tokens from standard input, one at a time,\n *      and converting each to a number, string, or boolean\n *  <li>those for reading characters from standard input, one at a time\n *  <li>those for reading lines from standard input, one at a time\n *  <li>those for reading a sequence of values of the same type from standard input,\n *      and returning the values in an array\n *  </ul>\n *  <p>\n *  Generally, it is best not to mix functions from the different\n *  categories in the same program.\n *  <p>\n *  <b>Getting started.</b>\n *  To use this class, you must have {@code StdIn.class} in your\n *  Java classpath. If you used our autoinstaller, you should be all set.\n *  Otherwise, either download\n *  <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  and add to your Java classpath or download\n *  <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdIn.java\">StdIn.java</a>\n *  and put a copy in your working directory.\n *  <p>\n *  <b>Reading tokens from standard input and converting to numbers and strings.</b>\n *  You can use the following methods to read numbers, strings, and booleans\n *  from standard input one at a time:\n *  <ul>\n *  <li> {@link #isEmpty()}\n *  <li> {@link #readInt()}\n *  <li> {@link #readDouble()}\n *  <li> {@link #readString()}\n *  <li> {@link #readShort()}\n *  <li> {@link #readLong()}\n *  <li> {@link #readFloat()}\n *  <li> {@link #readByte()}\n *  <li> {@link #readBoolean()}\n *  </ul>\n *  <p>\n *  The first method returns true if standard input has no more tokens.\n *  Each other method skips over any input that is whitespace. Then, it reads\n *  the next token and attempts to convert it into a value of the specified\n *  type. If it succeeds, it returns that value; otherwise, it\n *  throws an {@link InputMismatchException}.\n *  <p>\n *  <em>Whitespace</em> includes spaces, tabs, and newlines; the full definition\n *  is inherited from {@link Character#isWhitespace(char)}.\n *  A <em>token</em> is a maximal sequence of non-whitespace characters.\n *  The precise rules for describing which tokens can be converted to\n *  integers and floating-point numbers are inherited from\n *  <a href = \"http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#number-syntax\">Scanner</a>,\n *  using the locale {@link Locale#US}; the rules\n *  for floating-point numbers are slightly different\n *  from those in {@link Double#valueOf(String)},\n *  but unlikely to be of concern to most programmers.\n *  <p>\n *  As an example, the following code fragment reads integers from standard input,\n *  one at a time, and prints them one per line.\n *  <pre>\n *  while (!StdIn.isEmpty()) {\n *      double value = StdIn.readDouble();\n *      StdOut.println(value);\n *  }\n *  </pre>\n *  <p>\n *  <b>Reading characters from standard input.</b>\n *  You can use the following two methods to read characters from standard input one at a time:\n *  <ul>\n *  <li> {@link #hasNextChar()}\n *  <li> {@link #readChar()}\n *  </ul>\n *  <p>\n *  The first method returns true if standard input has more input (including whitespace).\n *  The second method reads and returns the next character of input on standard\n *  input (possibly a whitespace character).\n *  <p>\n *  As an example, the following code fragment reads characters from standard input,\n *  one character at a time, and prints it to standard output.\n *  <pre>\n *  while (StdIn.hasNextChar()) {\n *      char c = StdIn.readChar();\n *      StdOut.print(c);\n *  }\n *  </pre>\n *  <p>\n *  <b>Reading lines from standard input.</b>\n *  You can use the following two methods to read lines from standard input:\n *  <ul>\n *  <li> {@link #hasNextLine()}\n *  <li> {@link #readLine()}\n *  </ul>\n *  <p>\n *  The first method returns true if standard input has more input (including whitespace).\n *  The second method reads and returns the remaining portion of\n *  the next line of input on standard input (possibly whitespace),\n *  discarding the trailing line separator.\n *  <p>\n *  A <em>line separator</em> is defined to be one of the following strings:\n *  {@code \\n} (Linux), {@code \\r} (old Macintosh),\n *  {@code \\r\\n} (Windows),\n *  {@code \\}{@code u2028}, {@code \\}{@code u2029}, or {@code \\}{@code u0085}.\n *  <p>\n *  As an example, the following code fragment reads text from standard input,\n *  one line at a time, and prints it to standard output.\n *  <pre>\n *  while (StdIn.hasNextLine()) {\n *      String line = StdIn.readLine();\n *      StdOut.println(line);\n *  }\n *  </pre>\n *  <p>\n *  <b>Reading a sequence of values of the same type from standard input.</b>\n *  You can use the following methods to read a sequence numbers, strings,\n *  or booleans (all of the same type) from standard input:\n *  <ul>\n *  <li> {@link #readAllDoubles()}\n *  <li> {@link #readAllInts()}\n *  <li> {@link #readAllLongs()}\n *  <li> {@link #readAllStrings()}\n *  <li> {@link #readAllLines()}\n *  <li> {@link #readAll()}\n *  </ul>\n *  <p>\n *  The first three methods read of all of remaining token on standard input\n *  and converts the tokens to values of\n *  the specified type, as in the corresponding\n *  {@code readDouble}, {@code readInt}, and {@code readString()} methods.\n *  The {@code readAllLines()} method reads all remaining lines on standard\n *  input and returns them as an array of strings.\n *  The {@code readAll()} method reads all remaining input on standard\n *  input and returns it as a string.\n *  <p>\n *  As an example, the following code fragment reads all of the remaining\n *  tokens from standard input and returns them as an array of strings.\n *  <pre>\n *  String[] words = StdIn.readAllStrings();\n *  </pre>\n *  <p>\n *  <b>Differences with Scanner.</b>\n *  {@code StdIn} and {@link Scanner} are both designed to parse\n *  tokens and convert them to primitive types and strings.\n *  The main differences are summarized below:\n *  <ul>\n *  <li> {@code StdIn} is a set of static methods and reads\n *       reads input from only standard input. It is suitable for use before\n *       a programmer knows about objects.\n *       See {@link In} for an object-oriented version that handles\n *       input from files, URLs,\n *       and sockets.\n *  <li> {@code StdIn} uses whitespace as the delimiter pattern\n *       that separates tokens.\n *       {@link Scanner} supports arbitrary delimiter patterns.\n *  <li> {@code StdIn} coerces the character-set encoding to UTF-8,\n *       which is the most widely used character encoding for Unicode.\n *  <li> {@code StdIn} coerces the locale to {@link Locale#US},\n *       for consistency with {@link StdOut}, {@link Double#parseDouble(String)},\n *       and floating-point literals.\n *  <li> {@code StdIn} has convenient methods for reading a single\n *       character; reading in sequences of integers, doubles, or strings;\n *       and reading in all of the remaining input.\n *  </ul>\n *  <p>\n *  Historical note: {@code StdIn} preceded {@code Scanner}; when\n *  {@code Scanner} was introduced, this class was re-implemented to use {@code Scanner}.\n *  <p>\n *  <b>Using standard input.</b>\n *  Standard input is a fundamental operating system abstraction on Mac OS X,\n *  Windows, and Linux.\n *  The methods in {@code StdIn} are <em>blocking</em>, which means that they\n *  will wait until you enter input on standard input.\n *  If your program has a loop that repeats until standard input is empty,\n *  you must signal that the input is finished.\n *  To do so, depending on your operating system and IDE,\n *  use either {@code <Ctrl-d>} or {@code <Ctrl-z>}, on its own line.\n *  If you are redirecting standard input from a file, you will not need\n *  to do anything to signal that the input is finished.\n *  <p>\n *  <b>Known bugs.</b>\n *  Java's UTF-8 encoding does not recognize the optional\n *  <a href = \"http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\">byte-order mask</a>.\n *  If the input begins with the optional byte-order mask, {@code StdIn}\n *  will have an extra character {@code \\}{@code uFEFF} at the beginning.\n *  <p>\n *  <b>Reference.</b>\n *  For additional documentation,\n *  see <a href=\"https://introcs.cs.princeton.edu/15inout\">Section 1.5</a> of\n *  <em>Computer Science: An Interdisciplinary Approach</em>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n *  @author David Pritchard\n */\npublic final class StdIn {\n\n    /*** begin: section (1 of 2) of code duplicated from In to StdIn. */\n\n    // assume Unicode UTF-8 encoding\n    private static final String CHARSET_NAME = \"UTF-8\";\n\n    // assume language = English, country = US for consistency with System.out.\n    private static final Locale LOCALE = Locale.US;\n\n    // the default token separator; we maintain the invariant that this value\n    // is held by the scanner's delimiter between calls\n    private static final Pattern WHITESPACE_PATTERN = Pattern.compile(\"\\\\p{javaWhitespace}+\");\n\n    // makes whitespace significant\n    private static final Pattern EMPTY_PATTERN = Pattern.compile(\"\");\n\n    // used to read the entire input\n    private static final Pattern EVERYTHING_PATTERN = Pattern.compile(\"\\\\A\");\n\n    /*** end: section (1 of 2) of code duplicated from In to StdIn. */\n\n    private static Scanner scanner;\n\n    // it doesn't make sense to instantiate this class\n    private StdIn() { }\n\n    //// begin: section (2 of 2) of code duplicated from In to StdIn,\n    //// with all methods changed from \"public\" to \"public static\"\n\n   /**\n     * Returns true if standard input is empty (except possibly for whitespace).\n     * Use this method to know whether the next call to {@link #readString()},\n     * {@link #readDouble()}, etc. will succeed.\n     *\n     * @return {@code true} if standard input is empty (except possibly\n     *         for whitespace); {@code false} otherwise\n     */\n    public static boolean isEmpty() {\n        return !scanner.hasNext();\n    }\n\n   /**\n     * Returns true if standard input has a next line.\n     * Use this method to know whether the\n     * next call to {@link #readLine()} will succeed.\n     * This method is functionally equivalent to {@link #hasNextChar()}.\n     *\n     * @return {@code true} if standard input has more input (including whitespace);\n     *         {@code false} otherwise\n     */\n    public static boolean hasNextLine() {\n        return scanner.hasNextLine();\n    }\n\n    /**\n     * Returns true if standard input has more input (including whitespace).\n     * Use this method to know whether the next call to {@link #readChar()} will succeed.\n     * This method is functionally equivalent to {@link #hasNextLine()}.\n     *\n     * @return {@code true} if standard input has more input (including whitespace);\n     *         {@code false} otherwise\n     */\n    public static boolean hasNextChar() {\n        scanner.useDelimiter(EMPTY_PATTERN);\n        boolean result = scanner.hasNext();\n        scanner.useDelimiter(WHITESPACE_PATTERN);\n        return result;\n    }\n\n\n   /**\n     * Reads and returns the next line, excluding the line separator if present.\n     *\n     * @return the next line, excluding the line separator if present;\n     *         {@code null} if no such line\n     */\n    public static String readLine() {\n        String line;\n        try {\n            line = scanner.nextLine();\n        }\n        catch (NoSuchElementException e) {\n            line = null;\n        }\n        return line;\n    }\n\n    /**\n     * Reads and returns the next character.\n     *\n     * @return the next {@code char}\n     * @throws NoSuchElementException if standard input is empty\n     */\n    public static char readChar() {\n        try {\n            scanner.useDelimiter(EMPTY_PATTERN);\n            String ch = scanner.next();\n            assert ch.length() == 1 : \"Internal (Std)In.readChar() error!\"\n                + \" Please contact the authors.\";\n            scanner.useDelimiter(WHITESPACE_PATTERN);\n            return ch.charAt(0);\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'char' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads and returns the remainder of the input, as a string.\n     *\n     * @return the remainder of the input, as a string\n     * @throws NoSuchElementException if standard input is empty\n     */\n    public static String readAll() {\n        if (!scanner.hasNextLine())\n            return \"\";\n\n        String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();\n        // not that important to reset delimiter, since now scanner is empty\n        scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway\n        return result;\n    }\n\n\n   /**\n     * Reads the next token from standard input and returns it as a {@code String}.\n     *\n     * @return the next {@code String}\n     * @throws NoSuchElementException if standard input is empty\n     */\n    public static String readString() {\n        try {\n            return scanner.next();\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'String' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from standard input, parses it as an integer, and returns the integer.\n     *\n     * @return the next integer on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as an {@code int}\n     */\n    public static int readInt() {\n        try {\n            return scanner.nextInt();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read an 'int' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attemps to read an 'int' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n\n    }\n\n   /**\n     * Reads the next token from standard input, parses it as a double, and returns the double.\n     *\n     * @return the next double on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code double}\n     */\n    public static double readDouble() {\n        try {\n            return scanner.nextDouble();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'double' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'double' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from standard input, parses it as a float, and returns the float.\n     *\n     * @return the next float on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code float}\n     */\n    public static float readFloat() {\n        try {\n            return scanner.nextFloat();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'float' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'float' value from standard input, \"\n                                           + \"but there no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from standard input, parses it as a long integer, and returns the long integer.\n     *\n     * @return the next long integer on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code long}\n     */\n    public static long readLong() {\n        try {\n            return scanner.nextLong();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'long' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'long' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from standard input, parses it as a short integer, and returns the short integer.\n     *\n     * @return the next short integer on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code short}\n     */\n    public static short readShort() {\n        try {\n            return scanner.nextShort();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'short' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'short' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n   /**\n     * Reads the next token from standard input, parses it as a byte, and returns the byte.\n     *\n     * @return the next byte on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code byte}\n     */\n    public static byte readByte() {\n        try {\n            return scanner.nextByte();\n        }\n        catch (InputMismatchException e) {\n            String token = scanner.next();\n            throw new InputMismatchException(\"attempts to read a 'byte' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'byte' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n    }\n\n    /**\n     * Reads the next token from standard input, parses it as a boolean,\n     * and returns the boolean.\n     *\n     * @return the next boolean on standard input\n     * @throws NoSuchElementException if standard input is empty\n     * @throws InputMismatchException if the next token cannot be parsed as a {@code boolean}:\n     *    {@code true} or {@code 1} for true, and {@code false} or {@code 0} for false,\n     *    ignoring case\n     */\n    public static boolean readBoolean() {\n        try {\n            String token = readString();\n            if (\"true\".equalsIgnoreCase(token))  return true;\n            if (\"false\".equalsIgnoreCase(token)) return false;\n            if (\"1\".equals(token))               return true;\n            if (\"0\".equals(token))               return false;\n            throw new InputMismatchException(\"attempts to read a 'boolean' value from standard input, \"\n                                           + \"but the next token is \\\"\" + token + \"\\\"\");\n        }\n        catch (NoSuchElementException e) {\n            throw new NoSuchElementException(\"attempts to read a 'boolean' value from standard input, \"\n                                           + \"but no more tokens are available\");\n        }\n\n    }\n\n    /**\n     * Reads all remaining tokens from standard input and returns them as an array of strings.\n     *\n     * @return all remaining tokens on standard input, as an array of strings\n     */\n    public static String[] readAllStrings() {\n        // we could use readAll.trim().split(), but that's not consistent\n        // because trim() uses characters 0x00..0x20 as whitespace\n        String[] tokens = WHITESPACE_PATTERN.split(readAll());\n        if (tokens.length == 0 || tokens[0].length() > 0)\n            return tokens;\n\n        // don't include first token if it is leading whitespace\n        String[] decapitokens = new String[tokens.length-1];\n        for (int i = 0; i < tokens.length - 1; i++)\n            decapitokens[i] = tokens[i+1];\n        return decapitokens;\n    }\n\n    /**\n     * Reads all remaining lines from standard input and returns them as an array of strings.\n     * @return all remaining lines on standard input, as an array of strings\n     */\n    public static String[] readAllLines() {\n        ArrayList<String> lines = new ArrayList<String>();\n        while (hasNextLine()) {\n            lines.add(readLine());\n        }\n        return lines.toArray(new String[0]);\n    }\n\n    /**\n     * Reads all remaining tokens from standard input, parses them as integers, and returns\n     * them as an array of integers.\n     * @return all remaining integers on standard input, as an array\n     * @throws InputMismatchException if any token cannot be parsed as an {@code int}\n     */\n    public static int[] readAllInts() {\n        String[] fields = readAllStrings();\n        int[] vals = new int[fields.length];\n        for (int i = 0; i < fields.length; i++)\n            vals[i] = Integer.parseInt(fields[i]);\n        return vals;\n    }\n\n    /**\n     * Reads all remaining tokens from standard input, parses them as longs, and returns\n     * them as an array of longs.\n     * @return all remaining longs on standard input, as an array\n     * @throws InputMismatchException if any token cannot be parsed as a {@code long}\n     */\n    public static long[] readAllLongs() {\n        String[] fields = readAllStrings();\n        long[] vals = new long[fields.length];\n        for (int i = 0; i < fields.length; i++)\n            vals[i] = Long.parseLong(fields[i]);\n        return vals;\n    }\n\n    /**\n     * Reads all remaining tokens from standard input, parses them as doubles, and returns\n     * them as an array of doubles.\n     * @return all remaining doubles on standard input, as an array\n     * @throws InputMismatchException if any token cannot be parsed as a {@code double}\n     */\n    public static double[] readAllDoubles() {\n        String[] fields = readAllStrings();\n        double[] vals = new double[fields.length];\n        for (int i = 0; i < fields.length; i++)\n            vals[i] = Double.parseDouble(fields[i]);\n        return vals;\n    }\n\n    //// end: section (2 of 2) of code duplicated from In to StdIn\n\n    // do this once when StdIn is initialized\n    static {\n        resync();\n    }\n\n    /**\n     * If StdIn changes, use this to reinitialize the scanner.\n     */\n    private static void resync() {\n        setScanner(new Scanner(new java.io.BufferedInputStream(System.in), CHARSET_NAME));\n    }\n\n    private static void setScanner(Scanner scanner) {\n        StdIn.scanner = scanner;\n        StdIn.scanner.useLocale(LOCALE);\n    }\n\n   /**\n     * Reads all remaining tokens, parses them as integers, and returns\n     * them as an array of integers.\n     * @return all remaining integers, as an array\n     * @throws InputMismatchException if any token cannot be parsed as an {@code int}\n     * @deprecated Replaced by {@link #readAllInts()}.\n     */\n    @Deprecated\n    public static int[] readInts() {\n        return readAllInts();\n    }\n\n   /**\n     * Reads all remaining tokens, parses them as doubles, and returns\n     * them as an array of doubles.\n     * @return all remaining doubles, as an array\n     * @throws InputMismatchException if any token cannot be parsed as a {@code double}\n     * @deprecated Replaced by {@link #readAllDoubles()}.\n     */\n    @Deprecated\n    public static double[] readDoubles() {\n        return readAllDoubles();\n    }\n\n   /**\n     * Reads all remaining tokens and returns them as an array of strings.\n     * @return all remaining tokens, as an array of strings\n     * @deprecated Replaced by {@link #readAllStrings()}.\n     */\n    @Deprecated\n    public static String[] readStrings() {\n        return readAllStrings();\n    }\n\n\n    /**\n     * Interactive test of basic functionality.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        StdOut.print(\"Type a string: \");\n        String s = StdIn.readString();\n        StdOut.println(\"Your string was: \" + s);\n        StdOut.println();\n\n        StdOut.print(\"Type an int: \");\n        int a = StdIn.readInt();\n        StdOut.println(\"Your int was: \" + a);\n        StdOut.println();\n\n        StdOut.print(\"Type a boolean: \");\n        boolean b = StdIn.readBoolean();\n        StdOut.println(\"Your boolean was: \" + b);\n        StdOut.println();\n\n        StdOut.print(\"Type a double: \");\n        double c = StdIn.readDouble();\n        StdOut.println(\"Your double was: \" + c);\n        StdOut.println();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdOut.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdOut.java\n *  Execution:    java StdOut\n *  Dependencies: none\n *\n *  Writes data of various types to standard output.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.io.OutputStreamWriter;\nimport java.io.PrintWriter;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Locale;\n\n/**\n *  The {@code StdOut} class provides static methods for printing strings\n *  and numbers to standard output.\n *\n *  <p><b>Getting started.</b>\n *  To use this class, you must have {@code StdOut.class} in your\n *  Java classpath. If you used our autoinstaller, you should be all set.\n *  Otherwise, either download\n *  <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  and add to your Java classpath or download\n *  <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdOut.java\">StdOut.java</a>\n *  and put a copy in your working directory.\n *  <p>\n *  Here is an example program that uses {@code StdOut}:\n *  <pre>\n *   public class TestStdOut {\n *       public static void main(String[] args) {\n *           int a = 17;\n *           int b = 23;\n *           int sum = a + b;\n *           StdOut.println(\"Hello, World\");\n *           StdOut.printf(\"%d + %d = %d\\n\", a, b, sum);\n *       }\n *   }\n *  </pre>\n *  <p>\n *  <b>Differences with System.out.</b>\n *  The behavior of {@code StdOut} is similar to that of {@link System#out},\n *  but there are a few technical differences:\n *  <ul>\n *  <li> {@code StdOut} coerces the character-set encoding to UTF-8,\n *       which is a standard character encoding for Unicode.\n *  <li> {@code StdOut} coerces the locale to {@link Locale#US},\n *       for consistency with {@link StdIn}, {@link Double#parseDouble(String)},\n *       and floating-point literals.\n *  <li> {@code StdOut} <em>flushes</em> standard output after each call to\n *       {@code print()} so that text will appear immediately in the terminal.\n *  </ul>\n *  <p>\n *  <b>Reference.</b>\n *  For additional documentation,\n *  see <a href=\"https://introcs.cs.princeton.edu/15inout\">Section 1.5</a> of\n *  <em>Computer Science: An Interdisciplinary Approach</em>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdOut {\n\n    // force Unicode UTF-8 encoding; otherwise it's system dependent\n    private static final Charset CHARSET = StandardCharsets.UTF_8;\n\n    // assume language = English, country = US for consistency with StdIn\n    private static final Locale LOCALE = Locale.US;\n\n    // send output here\n    private static PrintWriter out;\n\n    // this is called before invoking any methods\n    static {\n        out = new PrintWriter(new OutputStreamWriter(System.out, CHARSET), true);\n    }\n\n    // don't instantiate\n    private StdOut() { }\n\n   /**\n     * Terminates the current line by printing the line-separator string.\n     */\n    public static void println() {\n        out.println();\n    }\n\n   /**\n     * Prints an object to this output stream and then terminates the line.\n     *\n     * @param x the object to print\n     */\n    public static void println(Object x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a boolean to standard output and then terminates the line.\n     *\n     * @param x the boolean to print\n     */\n    public static void println(boolean x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a character to standard output and then terminates the line.\n     *\n     * @param x the character to print\n     */\n    public static void println(char x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a double to standard output and then terminates the line.\n     *\n     * @param x the double to print\n     */\n    public static void println(double x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints an integer to standard output and then terminates the line.\n     *\n     * @param x the integer to print\n     */\n    public static void println(float x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints an integer to standard output and then terminates the line.\n     *\n     * @param x the integer to print\n     */\n    public static void println(int x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a long to standard output and then terminates the line.\n     *\n     * @param x the long to print\n     */\n    public static void println(long x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a short integer to standard output and then terminates the line.\n     *\n     * @param x the short to print\n     */\n    public static void println(short x) {\n        out.println(x);\n    }\n\n   /**\n     * Prints a byte to standard output and then terminates the line.\n     * <p>\n     * To write binary data, see {@link BinaryStdOut}.\n     *\n     * @param x the byte to print\n     */\n    public static void println(byte x) {\n        out.println(x);\n    }\n\n   /**\n     * Flushes standard output.\n     */\n    public static void print() {\n        out.flush();\n    }\n\n   /**\n     * Prints an object to standard output and flushes standard output.\n     *\n     * @param x the object to print\n     */\n    public static void print(Object x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a boolean to standard output and flushes standard output.\n     *\n     * @param x the boolean to print\n     */\n    public static void print(boolean x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a character to standard output and flushes standard output.\n     *\n     * @param x the character to print\n     */\n    public static void print(char x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a double to standard output and flushes standard output.\n     *\n     * @param x the double to print\n     */\n    public static void print(double x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a float to standard output and flushes standard output.\n     *\n     * @param x the float to print\n     */\n    public static void print(float x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints an integer to standard output and flushes standard output.\n     *\n     * @param x the integer to print\n     */\n    public static void print(int x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a long integer to standard output and flushes standard output.\n     *\n     * @param x the long integer to print\n     */\n    public static void print(long x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a short integer to standard output and flushes standard output.\n     *\n     * @param x the short integer to print\n     */\n    public static void print(short x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a byte to standard output and flushes standard output.\n     *\n     * @param x the byte to print\n     */\n    public static void print(byte x) {\n        out.print(x);\n        out.flush();\n    }\n\n   /**\n     * Prints a formatted string to standard output, using the specified format\n     * string and arguments, and then flushes standard output.\n     *\n     *\n     * @param format the <a href = \"http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax\">format string</a>\n     * @param args   the arguments accompanying the format string\n     */\n    public static void printf(String format, Object... args) {\n        out.printf(LOCALE, format, args);\n        out.flush();\n    }\n\n   /**\n     * Prints a formatted string to standard output, using the locale and\n     * the specified format string and arguments; then flushes standard output.\n     *\n     * @param locale the locale\n     * @param format the <a href = \"http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax\">format string</a>\n     * @param args   the arguments accompanying the format string\n     */\n    public static void printf(Locale locale, String format, Object... args) {\n        out.printf(locale, format, args);\n        out.flush();\n    }\n\n   /**\n     * Unit tests some methods in {@code StdOut}.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // write to stdout\n        StdOut.println(\"Test\");\n        StdOut.println(17);\n        StdOut.println(true);\n        StdOut.printf(\"%.6f\\n\", 1.0/7.0);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdPicture.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdPicture.java\n *  Execution:    java StdPicture filename.jpg\n *  Dependencies: Picture.java\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code StdPicture} class provides static methods for manipulating\n *  the individual pixels of an image using the RGB color model.\n *  You can either initialize a blank image (of a given dimension) or read an\n *  image in a supported file format (typically JPEG, PNG, GIF, TIFF, and BMP).\n *  This class also includes methods for displaying the image in a window\n *  and saving it to a file.\n *\n *  <p>\n *  <b>Use in the curriculum.</b>\n *  The {@code StdPicture} class is intended for early usage in the\n *  curriculum, before objects.\n *  The {@link Picture} class is an object-oriented version that supports\n *  manipulating multiple pictures at the same time.\n *\n *  <p>\n *  <b>Getting started.</b>\n *  To use this class, you must have {@code StdPicture} in your Java classpath.\n *  Here are three possible ways to do this:\n *  <ul>\n *  <li> If you ran our autoinstaller, use the commands\n *  {@code javac-introcs} and {@code java-introcs} (or {@code javac-algs4}\n *  and {@code java-algs4}) when compiling and executing. These commands\n *  add {@code stdlib.jar} (or {@code algs4.jar}) to the Java classpath, which\n *  provides access to {@code StdPicture}.\n *\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/code/stdlib.jar\">stdlib.jar</a>\n *  (or <a href = \"https://algs4.cs.princeton.edu/code/algs4.jar\">algs4.jar</a>)\n *  and add it to the Java classpath.\n *\n *  <li> Download <a href = \"https://introcs.cs.princeton.edu/java/stdlib/StdPicture.java\">StdPicture.java</a>\n *  and\n *  <a href = \"https://introcs.cs.princeton.edu/java/stdlib/Picture.java\">Picture.java</a>\n *  and put them in the working directory.\n *  </ul>\n *\n *  <p>\n *  As a test, cut-and-paste the following short program into your editor:\n *  <pre>\n *   public class TestStdPicture {\n *       public static void main(String[] args) {\n *           StdPicture.read(\"https://introcs.cs.princeton.edu/java/stdlib/mandrill.jpg\");\n *           StdPicture.show();\n *       }\n *   }\n *  </pre>\n *  <p>\n *  If you compile and execute the program, you should see a picture of a mandrill\n *  (a colorful monkey native to west-central Africa) in a window.\n *\n *  <p>\n *  <b>Anatomy of an image.</b>\n *  An image is a <em>width</em>-by-<em>height</em> grid of pixels, with pixel (0, 0)\n *  in the upper-left corner.\n *  Each pixel has a color that is represented using the <em>RGB color model</em>,\n *  which specifies the levels of <em>red</em> (R), <em>green</em> (G), and <em>blue</em> (B)\n *  on an integer scale from 0 to 255.\n *\n *  <blockquote>\n *  <img src = \"https://introcs.cs.princeton.edu/java/stdlib/AnatomyImage.png\" width = 200 alt = \"anatomy of an image\">\n *  </blockquote>\n *\n *  <p>\n *  <b>Initializing the picture.</b>\n *  You can use the following methods to initialize the picture:\n *  <ul>\n *  <li> {@link #read(String filename)}\n *  <li> {@link #init(int width, int height)}\n *  </ul>\n *  <p>\n *  The first method reads an image in a supported file format\n *  (typically JPEG, PNG, GIF, TIFF, and BMP)\n *  and initializes the picture to that image.\n *  The second method initializes a <em>width</em>-by-<em>height</em>\n *  picture, with each pixel black.\n *\n *  <p>\n *  <b>Getting and setting the colors of the individual pixels.</b>\n *  You can use the following methods to retrieve the RGB components\n *  of a specified pixel:\n *  <ul>\n *  <li> {@link #getRed(int col, int row)}\n *  <li> {@link #getGreen(int col, int row)}\n *  <li> {@link #getBlue(int col, int row)}\n *  <li> {@link #setRGB(int col, int row, int r, int g, int b)}\n *  </ul>\n *  <p>\n *  The first three methods return the red, green, and blue components of pixel\n *  (<em>col</em>, <em>row</em>). Each component is an integer between 0 and 255,\n *  with 0 corresponding to the absence of that component and 255 corresponding\n *  to full intensity of that component.\n *  The last method sets the red, green, and blue components of pixel\n *  (<em>col</em>, <em>row</em>) to the specified values.\n *\n *  <p><b>Iterating over the pixels.</b>\n *  A common operation in image processing is to iterate over and process\n *  all of the pixels in an image.\n *  Here is a prototypical example that converts a color image\n *  to grayscale, using the NTSC formula\n *  <em>Y</em> = 0.299<em>r</em> + 0.587<em>g</em> + 0.114<em>b</em>.\n *  Note that if the red, green, and blue components are all equal,\n *  then the color is a shade of gray.\n *  <pre>\n *  StdPicture.read(\"https://introcs.cs.princeton.edu/java/stdlib/mandrill.jpg\");\n *  for (int col = 0; col &lt; StdPicture.width(); col++) {\n *      for (int row = 0; row &lt; StdPicture.height(); row++) {\n *          int r = StdPicture.getRed(col, row);\n *          int g = StdPicture.getGreen(col, row);\n *          int b = StdPicture.getBlue(col, row);\n *          int y = (int) (Math.round(0.299*r + 0.587*g + 0.114*b));\n *          StdPicture.setRGB(col, row, y, y, y);\n *      }\n *  }\n *  StdPicture.show();\n *  </pre>\n *\n *  <p><b>Transparency.</b>\n *  The {@code StdPicture} class supports transparent images, using the\n *  ARGB color model. The following methods are useful for this:\n *  <ul>\n *  <li> {@link #getAlpha(int col, int row)}\n *  <li> {@link #setARGB(int col, int row, int a, int r, int g, int b)}\n *  </ul>\n *  <p>\n *  The first method gets the alpha component of pixel (<em>col</em>, <em>row</em>).\n *  The second methods sets the alpha, red, green, and bluecomponents of\n *  pixel (<em>col</em>, <em>row</em>).\n *  The alpha value defines the transparency of a color, with 0 corresponding to\n *  completely transparent and 255 to completely opaque. If transparency is not\n *  explicitly used, the alpha value is 255.\n *\n *  <p><b>Saving files.</b>\n *  The {@code StdPicture} class supports writing images to a supported\n *  file format (typically JPEG, PNG, GIF, TIFF, and BMP).\n *  You can save the picture to a file two method:\n *  <ul>\n *  <li> {@link #save(String filename)}\n *  </ul>\n *\n *  <p>Alternatively, you can save the picture interactively\n *  by using the menu option <em>File → Save</em> from the picture window.\n *\n *  <p><b>File formats.</b>\n *  The {@code StdPicture} class supports reading and writing images to any of the\n *  file formats supported by {@link javax.imageio} (typically JPEG, PNG,\n *  GIF, TIFF, and BMP).\n *  The file extensions corresponding to JPEG, PNG, GIF, TIFF, and BMP,\n *  are {@code .jpg}, {@code .png}, {@code .gif}, {@code .tif},\n *  and {@code .bmp}, respectively.\n *  The file formats JPEG and BMP do not support transparency.\n *\n *  <p><b>Memory usage.</b>\n *  A <em>W</em>-by-<em>H</em> picture uses ~ 4 <em>W H</em> bytes of memory,\n *  since the color of each pixel is encoded as a 32-bit <code>int</code>.\n *\n *  <p><b>Additional documentation.</b>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/31datatype\">Section 3.1</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdPicture {\n\n    // the default picture width and height\n    private static final int DEFAULT_SIZE = 512;\n\n    // the underlying picture\n    private static Picture picture = new Picture(DEFAULT_SIZE, DEFAULT_SIZE);\n\n    // singleton pattern: client can't instantiate\n    private StdPicture() { }\n\n   /**\n     * Initializes a {@code width}-by-{@code height} picture, with {@code width} columns\n     * and {@code height} rows, where each pixel is black.\n     *\n     * @param width the width of the picture\n     * @param height the height of the picture\n     * @throws IllegalArgumentException if {@code width} is negative or zero\n     * @throws IllegalArgumentException if {@code height} is negative or zero\n     */\n    public static void init(int width, int height) {\n        if (picture.isVisible()) {\n            hide();\n            picture = new Picture(width, height);\n            show();\n        }\n        else {\n            picture = new Picture(width, height);\n        }\n    }\n\n   /**\n     * Initializes the picture by reading a JPEG, PNG, GIF, BMP, or TIFF image\n     * from a file or URL.\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     *\n     * @param  filename the name of the file or URL\n     * @throws IllegalArgumentException if cannot read image\n     * @throws IllegalArgumentException if {@code name} is {@code null}\n     */\n    public static void read(String filename) {\n        Picture newPicture = new Picture(filename);\n\n        // same dimension, so copy pixels instead of using new Picture and GUI\n        if (newPicture.width() == picture.width() && newPicture.height() == picture.height()) {\n            for (int col = 0; col < picture.width(); col++) {\n                for (int row = 0; row < picture.height(); row++) {\n                    picture.setARGB(col, row, newPicture.getARGB(col, row));\n                }\n            }\n        }\n\n        // different dimension, so need to use new Picture and GUI\n        else if (picture.isVisible()) {\n            hide();\n            picture = newPicture;\n            show();\n        }\n\n        // no GUI, so use the new Picture\n        else {\n            picture = newPicture;\n        }\n    }\n\n   /**\n     * Is the window containing the picture visible?\n     * @return {@code true} if the picture is visible, and {@code false} otherwise\n     */\n    public static boolean isVisible() {\n        return picture.isVisible();\n    }\n\n   /**\n     * Displays the picture in a window on the screen.\n     */\n    public static void show() {\n        picture.show();\n    }\n\n   /**\n     * Hides the window containing the picture.\n     */\n    public static void hide() {\n        picture.hide();\n    }\n\n    /**\n     * Pauses for t milliseconds. This method is intended to support computer animation.\n     * @param t number of milliseconds\n     * @throws IllegalArgumentException if {@code t} is negative\n     */\n    public static void pause(int t) {\n        if (t < 0) throw new IllegalArgumentException(\"argument must be non-negative\");\n        try {\n            Thread.sleep(t);\n        }\n        catch (InterruptedException e) {\n            System.out.println(\"Error sleeping\");\n        }\n    }\n\n   /**\n     * Returns the height of the picture.\n     *\n     * @return the height of the picture (in pixels)\n     */\n    public static int height() {\n        return picture.height();\n    }\n\n   /**\n     * Returns the width of the picture.\n     *\n     * @return the width of the picture (in pixels)\n     */\n    public static int width() {\n        return picture.width();\n    }\n\n   /**\n     * Returns the alpha component of the color of pixel ({@code col}, {@code row}).\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the alpha component of the color of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public static int getAlpha(int col, int row) {\n        int rgb = picture.getARGB(col, row);\n        return (rgb >> 24) & 0xFF;\n    }\n\n   /**\n     * Returns the red component of the color of pixel ({@code col}, {@code row}).\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the red component of the color of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public static int getRed(int col, int row) {\n        int rgb = picture.getARGB(col, row);\n        return (rgb >> 16) & 0xFF;\n    }\n\n   /**\n     * Returns the green component of the color of pixel ({@code col}, {@code row}).\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the green component of the color of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public static int getGreen(int col, int row) {\n        int rgb = picture.getARGB(col, row);\n        return (rgb >> 8) & 0xFF;\n    }\n\n   /**\n     * Returns the blue component of the color of pixel ({@code col}, {@code row}).\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the blue component of the color of pixel ({@code col}, {@code row})\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public static int getBlue(int col, int row) {\n        int rgb = picture.getARGB(col, row);\n        return (rgb >> 0) & 0xFF;\n    }\n\n   /**\n     * Returns the ARGB color of pixel ({@code col}, {@code row}).\n     *\n     * @param col the column index\n     * @param row the row index\n     * @return the ARGB color of pixel ({@code col}, {@code row} as a 32-bit integer\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public static int getARGB(int col, int row) {\n        int argb = picture.getARGB(col, row);\n        return argb;\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given RGB color using\n     * red, green, and blue components. The alpha component is set to 255 (no transparency).\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param r the red component of the color\n     * @param g the green component of the color\n     * @param b the blue component of the color\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     * @throws IllegalArgumentException unless {@code 0 <= r < 256}, {@code 0 <= g < 256},\n     *                                  and {@code 0 <= b < 256}.\n     */\n    public static void setRGB(int col, int row, int r, int g, int b) {\n        validateComponent(r, \"red\");\n        validateComponent(g, \"green\");\n        validateComponent(b, \"blue\");\n        int a = 255;\n        int argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);\n        picture.setARGB(col, row, argb);\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given ARGB color using\n     * alpha, red, green, and blue components.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param a the alpha component of the color\n     * @param r the red component of the color\n     * @param g the green component of the color\n     * @param b the blue component of the color\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     * @throws IllegalArgumentException unless {@code 0 <= a < 256}, {@code 0 <= r < 256},\n     *                                         {@code 0 <= g < 256}, and {@code 0 <= b < 256}.\n     */\n    public static void setARGB(int col, int row, int a, int r, int g, int b) {\n        validateComponent(a, \"alpha\");\n        validateComponent(r, \"red\");\n        validateComponent(g, \"green\");\n        validateComponent(b, \"blue\");\n\n        // internally represented using ARGB, not RGBA\n        int argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);\n        picture.setARGB(col, row, argb);\n    }\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given RGB color.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param rgb the RGB color, represented as a 24-bit integer\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     * @throws IllegalArgumentException unless {@code 0 <= rgb < 2^24}.\n     */\n/*\n    public static void setRGB(int col, int row, int rgb) {\n        int a = 255;\n        int argb = (a << 24) | (rgb);\n        picture.setARGB(col, row, argb);\n    }\n*/\n\n   /**\n     * Sets the color of pixel ({@code col}, {@code row}) to the given ARGB color.\n     *\n     * @param col the column index\n     * @param row the row index\n     * @param argb the ARGB color, represented as a 32-bit integer\n     * @throws IndexOutOfBoundsException unless both {@code 0 <= col < width} and {@code 0 <= row < height}\n     */\n    public static void setARGB(int col, int row, int argb) {\n        picture.setARGB(col, row, argb);\n    }\n\n\n    /**\n     * Sets the title of this picture.\n     * @param title the title\n     * @throws IllegalArgumentException if {@code title} is {@code null}\n     */\n    public static void setTitle(String title) {\n        picture.setTitle(title);\n    }\n\n   /**\n     * Saves the picture to a file in a supported file format\n     * (typically JPEG, PNG, GIF, TIFF, and BMP).\n     * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif},\n     * {@code .bmp}, or {@code .tif}.\n     * If the file format does not support transparency (such as JPEG\n     * or BMP), it will be converted to be opaque (with purely\n     * transparent pixels converted to black).\n     *\n     * @param filename the name of the file\n     * @throws IllegalArgumentException if {@code filename} is {@code null}\n     * @throws IllegalArgumentException if {@code filename} is the empty string\n     */\n    public static void save(String filename) {\n        picture.save(filename);\n    }\n\n    private static void validateComponent(int val, String name) {\n        if (val < 0 || val >= 256) {\n            throw new IllegalArgumentException(name + \" must be between 0 and 255\");\n        }\n    }\n\n   /**\n     * Unit tests this {@code StdPicture} data type.\n     * Reads a picture specified by the command-line argument,\n     * and shows it in a window on the screen.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        StdPicture.read(args[0]);\n        System.out.printf(\"%d-by-%d\\n\", picture.width(), picture.height());\n        StdPicture.show();\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdRandom.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdRandom.java\n *  Execution:    java StdRandom\n *  Dependencies: StdOut.java\n *\n *  A library of static methods to generate pseudo-random numbers from\n *  different distributions (bernoulli, uniform, gaussian, discrete,\n *  and exponential). Also includes a method for shuffling an array.\n *\n *\n *  %  java StdRandom 5\n *  seed = 1316600602069\n *  59 16.81826  true 8.83954  0\n *  32 91.32098  true 9.11026  0\n *  35 10.11874  true 8.95396  3\n *  92 32.88401  true 8.87089  0\n *  72 92.55791  true 9.46241  0\n *\n *  % java StdRandom 5\n *  seed = 1316600616575\n *  96 60.17070  true 8.72821  0\n *  79 32.01607  true 8.58159  0\n *  81 59.49065  true 9.10423  1\n *  96 51.65818  true 9.02102  0\n *  99 17.55771  true 8.99762  0\n *\n *  % java StdRandom 5 1316600616575\n *  seed = 1316600616575\n *  96 60.17070  true 8.72821  0\n *  79 32.01607  true 8.58159  0\n *  81 59.49065  true 9.10423  1\n *  96 51.65818  true 9.02102  0\n *  99 17.55771  true 8.99762  0\n *\n *\n *  Remark\n *  ------\n *    - Relies on randomness of nextDouble() method in java.util.Random\n *      to generate pseudo-random numbers in [0, 1).\n *\n *    - This library allows you to set and get the pseudo-random number seed.\n *\n *    - See http://www.honeylocust.com/RngPack/ for an industrial\n *      strength random number generator in Java.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Random;\n\n/**\n *  The {@code StdRandom} class provides static methods for generating\n *  random number from various discrete and continuous distributions,\n *  including uniform, Bernoulli, geometric, Gaussian, exponential, Pareto,\n *  Poisson, and Cauchy. It also provides method for shuffling an\n *  array or subarray and generating random permutations.\n *\n *  <p><b>Conventions.</b>\n *  By convention, all intervals are half open. For example,\n *  <code>uniformDouble(-1.0, 1.0)</code> returns a random number between\n *  <code>-1.0</code> (inclusive) and <code>1.0</code> (exclusive).\n *  Similarly, <code>shuffle(a, lo, hi)</code> shuffles the <code>hi - lo</code>\n *  elements in the array <code>a[]</code>, starting at index <code>lo</code>\n *  (inclusive) and ending at index <code>hi</code> (exclusive).\n *\n *  <p><b>Performance.</b>\n *  The methods all take constant expected time, except those that involve arrays.\n *  The <em>shuffle</em> method takes time linear in the subarray to be shuffled;\n *  the <em>discrete</em> methods take time linear in the length of the argument\n *  array.\n *\n *  <p><b>Additional information.</b>\n *  For additional documentation,\n *  see <a href=\"https://introcs.cs.princeton.edu/22library\">Section 2.2</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdRandom {\n\n    private static Random random;    // pseudo-random number generator\n    private static long seed;        // pseudo-random number generator seed\n\n    // static initializer\n    static {\n        // this is how the seed was set in Java 1.4\n        seed = System.currentTimeMillis();\n        random = new Random(seed);\n    }\n\n    // don't instantiate\n    private StdRandom() { }\n\n    /**\n     * Sets the seed of the pseudo-random number generator.\n     * This method enables you to produce the same sequence of \"random\"\n     * number for each execution of the program.\n     * Ordinarily, you should call this method at most once per program.\n     *\n     * @param s the seed\n     */\n    public static void setSeed(long s) {\n        seed   = s;\n        random = new Random(seed);\n    }\n\n    /**\n     * Returns the seed of the pseudo-random number generator.\n     *\n     * @return the seed\n     */\n    public static long getSeed() {\n        return seed;\n    }\n\n    /**\n     * Returns a random real number uniformly in [0, 1).\n     *\n     * @return a random real number uniformly in [0, 1)\n     * @deprecated Replaced by {@link #uniformDouble()}.\n     */\n     @Deprecated\n    public static double uniform() {\n        return uniformDouble();\n    }\n\n    /**\n     * Returns a random real number uniformly in [0, 1).\n     *\n     * @return a random real number uniformly in [0, 1)\n     */\n    public static double uniformDouble() {\n        return random.nextDouble();\n    }\n\n    /**\n     * Returns a random integer uniformly in [0, n).\n     *\n     * @param n number of possible integers\n     * @return a random integer uniformly between 0 (inclusive) and {@code n} (exclusive)\n     * @throws IllegalArgumentException if {@code n <= 0}\n     * @deprecated Replaced by {@link #uniformInt(int n)}.\n     */\n     @Deprecated\n    public static int uniform(int n) {\n        return uniformInt(n);\n    }\n\n    /**\n     * Returns a random integer uniformly in [0, n).\n     *\n     * @param n number of possible integers\n     * @return a random integer uniformly between 0 (inclusive) and {@code n} (exclusive)\n     * @throws IllegalArgumentException if {@code n <= 0}\n     */\n    public static int uniformInt(int n) {\n        if (n <= 0) throw new IllegalArgumentException(\"argument must be positive: \" + n);\n        return random.nextInt(n);\n    }\n\n    /**\n     * Returns a random long integer uniformly in [0, n).\n     *\n     * @param n number of possible {@code long} integers\n     * @return a random long integer uniformly between 0 (inclusive) and {@code n} (exclusive)\n     * @throws IllegalArgumentException if {@code n <= 0}\n     * @deprecated Replaced by {@link #uniformLong(long n)}.\n     */\n    @Deprecated\n    public static long uniform(long n) {\n        return uniformLong(n);\n    }\n\n    /**\n     * Returns a random long integer uniformly in [0, n).\n     *\n     * @param n number of possible {@code long} integers\n     * @return a random long integer uniformly between 0 (inclusive) and {@code n} (exclusive)\n     * @throws IllegalArgumentException if {@code n <= 0}\n     */\n    public static long uniformLong(long n) {\n        if (n <= 0L) throw new IllegalArgumentException(\"argument must be positive: \" + n);\n\n        // https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long-\n        long r = random.nextLong();\n        long m = n - 1;\n\n        // power of two\n        if ((n & m) == 0L) {\n            return r & m;\n        }\n\n        // reject over-represented candidates\n        long u = r >>> 1;\n        while (u + m - (r = u % n) < 0L) {\n            u = random.nextLong() >>> 1;\n        }\n        return r;\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //  STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA\n    //  THE STATIC METHODS ABOVE.\n    ///////////////////////////////////////////////////////////////////////////\n\n    /**\n     * Returns a random real number uniformly in [0, 1).\n     *\n     * @return     a random real number uniformly in [0, 1)\n     * @deprecated Replaced by {@link #uniformDouble()}.\n     */\n    @Deprecated\n    public static double random() {\n        return uniformDouble();\n    }\n\n    /**\n     * Returns a random integer uniformly in [a, b).\n     *\n     * @param  a the left endpoint\n     * @param  b the right endpoint\n     * @return a random integer uniformly in [a, b)\n     * @throws IllegalArgumentException if {@code b <= a}\n     * @throws IllegalArgumentException if {@code b - a >= Integer.MAX_VALUE}\n     * @deprecated Replaced by {@link #uniformInt(int a, int b)}.\n     */\n    @Deprecated\n    public static int uniform(int a, int b) {\n        return uniformInt(a, b);\n    }\n\n    /**\n     * Returns a random integer uniformly in [a, b).\n     *\n     * @param  a the left endpoint\n     * @param  b the right endpoint\n     * @return a random integer uniformly in [a, b)\n     * @throws IllegalArgumentException if {@code b <= a}\n     * @throws IllegalArgumentException if {@code b - a >= Integer.MAX_VALUE}\n     */\n    public static int uniformInt(int a, int b) {\n        if ((b <= a) || ((long) b - a >= Integer.MAX_VALUE)) {\n            throw new IllegalArgumentException(\"invalid range: [\" + a + \", \" + b + \")\");\n        }\n        return a + uniform(b - a);\n    }\n\n    /**\n     * Returns a random real number uniformly in [a, b).\n     *\n     * @param  a the left endpoint\n     * @param  b the right endpoint\n     * @return a random real number uniformly in [a, b)\n     * @throws IllegalArgumentException unless {@code a < b}\n     * @deprecated Replaced by {@link #uniformDouble(double a, double b)}.\n     */\n    @Deprecated\n    public static double uniform(double a, double b) {\n        return uniformDouble(a, b);\n    }\n\n    /**\n     * Returns a random real number uniformly in [a, b).\n     *\n     * @param  a the left endpoint\n     * @param  b the right endpoint\n     * @return a random real number uniformly in [a, b)\n     * @throws IllegalArgumentException unless {@code a < b}\n     */\n    public static double uniformDouble(double a, double b) {\n        if (!(a < b)) {\n            throw new IllegalArgumentException(\"invalid range: [\" + a + \", \" + b + \")\");\n        }\n        return a + uniform() * (b-a);\n    }\n\n    /**\n     * Returns a random boolean from a Bernoulli distribution with success\n     * probability <em>p</em>.\n     *\n     * @param  p the probability of returning {@code true}\n     * @return {@code true} with probability {@code p} and\n     *         {@code false} with probability {@code 1 - p}\n     * @throws IllegalArgumentException unless {@code 0} &le; {@code p} &le; {@code 1.0}\n     */\n    public static boolean bernoulli(double p) {\n        if (!(p >= 0.0 && p <= 1.0))\n            throw new IllegalArgumentException(\"probability p must be between 0.0 and 1.0: \" + p);\n        return uniformDouble() < p;\n    }\n\n    /**\n     * Returns a random boolean from a Bernoulli distribution with success\n     * probability 1/2.\n     *\n     * @return {@code true} with probability 1/2 and\n     *         {@code false} with probability 1/2\n     */\n    public static boolean bernoulli() {\n        return bernoulli(0.5);\n    }\n\n    /**\n     * Returns a random real number from a standard Gaussian distribution.\n     *\n     * @return a random real number from a standard Gaussian distribution\n     *         (mean 0 and standard deviation 1).\n     */\n    public static double gaussian() {\n        // use the polar form of the Box-Muller transform\n        double r, x, y;\n        do {\n            x = uniformDouble(-1.0, 1.0);\n            y = uniformDouble(-1.0, 1.0);\n            r = x*x + y*y;\n        } while (r >= 1 || r == 0);\n        return x * Math.sqrt(-2 * Math.log(r) / r);\n\n        // Remark:  y * Math.sqrt(-2 * Math.log(r) / r)\n        // is an independent random gaussian\n    }\n\n    /**\n     * Returns a random real number from a Gaussian distribution with mean &mu;\n     * and standard deviation &sigma;.\n     *\n     * @param  mu the mean\n     * @param  sigma the standard deviation\n     * @return a real number distributed according to the Gaussian distribution\n     *         with mean {@code mu} and standard deviation {@code sigma}\n     */\n    public static double gaussian(double mu, double sigma) {\n        return mu + sigma * gaussian();\n    }\n\n    /**\n     * Returns a random integer from a geometric distribution with success\n     * probability <em>p</em>.\n     * The integer represents the number of independent trials\n     * before the first success.\n     *\n     * @param  p the parameter of the geometric distribution\n     * @return a random integer from a geometric distribution with success\n     *         probability {@code p}; or {@code Integer.MAX_VALUE} if\n     *         {@code p} is (nearly) equal to {@code 1.0}.\n     * @throws IllegalArgumentException unless {@code p >= 0.0} and {@code p <= 1.0}\n     */\n    public static int geometric(double p) {\n        if (!(p >= 0)) {\n            throw new IllegalArgumentException(\"probability p must be greater than 0: \" + p);\n        }\n        if (!(p <= 1.0)) {\n            throw new IllegalArgumentException(\"probability p must not be larger than 1: \" + p);\n        }\n        // using algorithm given by Knuth\n        return (int) Math.ceil(Math.log(uniformDouble()) / Math.log(1.0 - p));\n    }\n\n    /**\n     * Returns a random integer from a Poisson distribution with mean &lambda;.\n     *\n     * @param  lambda the mean of the Poisson distribution\n     * @return a random integer from a Poisson distribution with mean {@code lambda}\n     * @throws IllegalArgumentException unless {@code lambda > 0.0} and not infinite\n     */\n    public static int poisson(double lambda) {\n        if (!(lambda > 0.0))\n            throw new IllegalArgumentException(\"lambda must be positive: \" + lambda);\n        if (Double.isInfinite(lambda))\n            throw new IllegalArgumentException(\"lambda must not be infinite: \" + lambda);\n        // using algorithm given by Knuth\n        // see http://en.wikipedia.org/wiki/Poisson_distribution\n        int k = 0;\n        double p = 1.0;\n        double expLambda = Math.exp(-lambda);\n        do {\n            k++;\n            p *= uniformDouble();\n        } while (p >= expLambda);\n        return k-1;\n    }\n\n    /**\n     * Returns a random real number from the standard Pareto distribution.\n     *\n     * @return a random real number from the standard Pareto distribution\n     */\n    public static double pareto() {\n        return pareto(1.0);\n    }\n\n    /**\n     * Returns a random real number from a Pareto distribution with\n     * shape parameter &alpha;.\n     *\n     * @param  alpha shape parameter\n     * @return a random real number from a Pareto distribution with shape\n     *         parameter {@code alpha}\n     * @throws IllegalArgumentException unless {@code alpha > 0.0}\n     */\n    public static double pareto(double alpha) {\n        if (!(alpha > 0.0))\n            throw new IllegalArgumentException(\"alpha must be positive: \" + alpha);\n        return Math.pow(1 - uniformDouble(), -1.0 / alpha) - 1.0;\n    }\n\n    /**\n     * Returns a random real number from the Cauchy distribution.\n     *\n     * @return a random real number from the Cauchy distribution.\n     */\n    public static double cauchy() {\n        return Math.tan(Math.PI * (uniformDouble() - 0.5));\n    }\n\n    /**\n     * Returns a random integer from the specified discrete distribution.\n     *\n     * @param  probabilities the probability of occurrence of each integer\n     * @return a random integer from a discrete distribution:\n     *         {@code i} with probability {@code probabilities[i]}\n     * @throws IllegalArgumentException if {@code probabilities} is {@code null}\n     * @throws IllegalArgumentException if sum of array entries is not (very nearly) equal to {@code 1.0}\n     * @throws IllegalArgumentException unless {@code probabilities[i] >= 0.0} for each index {@code i}\n     */\n    public static int discrete(double[] probabilities) {\n        if (probabilities == null) throw new IllegalArgumentException(\"argument array must not be null\");\n        double EPSILON = 1.0E-14;\n        double sum = 0.0;\n        for (int i = 0; i < probabilities.length; i++) {\n            if (!(probabilities[i] >= 0.0))\n                throw new IllegalArgumentException(\"array entry \" + i + \" must be non-negative: \" + probabilities[i]);\n            sum += probabilities[i];\n        }\n        if (sum > 1.0 + EPSILON || sum < 1.0 - EPSILON)\n            throw new IllegalArgumentException(\"sum of array entries does not approximately equal 1.0: \" + sum);\n\n        // the for loop may not return a value when both r is (nearly) 1.0 and when the\n        // cumulative sum is less than 1.0 (as a result of floating-point roundoff error)\n        while (true) {\n            double r = uniformDouble();\n            sum = 0.0;\n            for (int i = 0; i < probabilities.length; i++) {\n                sum = sum + probabilities[i];\n                if (sum > r) return i;\n            }\n        }\n    }\n\n    /**\n     * Returns a random integer from the specified discrete distribution.\n     *\n     * @param  frequencies the frequency of occurrence of each integer\n     * @return a random integer from a discrete distribution:\n     *         {@code i} with probability proportional to {@code frequencies[i]}\n     * @throws IllegalArgumentException if {@code frequencies} is {@code null}\n     * @throws IllegalArgumentException if all array entries are {@code 0}\n     * @throws IllegalArgumentException if {@code frequencies[i]} is negative for any index {@code i}\n     * @throws IllegalArgumentException if sum of frequencies exceeds {@code Integer.MAX_VALUE} (2<sup>31</sup> - 1)\n     */\n    public static int discrete(int[] frequencies) {\n        if (frequencies == null) throw new IllegalArgumentException(\"argument array must not be null\");\n        long sum = 0;\n        for (int i = 0; i < frequencies.length; i++) {\n            if (frequencies[i] < 0)\n                throw new IllegalArgumentException(\"array entry \" + i + \" must be non-negative: \" + frequencies[i]);\n            sum += frequencies[i];\n        }\n        if (sum == 0)\n            throw new IllegalArgumentException(\"at least one array entry must be positive\");\n        if (sum >= Integer.MAX_VALUE)\n            throw new IllegalArgumentException(\"sum of frequencies overflows an int\");\n\n        // pick index i with probability proportional to frequency\n        double r = uniformInt((int) sum);\n        sum = 0;\n        for (int i = 0; i < frequencies.length; i++) {\n            sum += frequencies[i];\n            if (sum > r) return i;\n        }\n\n        // can't reach here\n        assert false;\n        return -1;\n    }\n\n    /**\n     * Returns a random real number from an exponential distribution\n     * with rate &lambda;.\n     *\n     * @param  lambda the rate of the exponential distribution\n     * @return a random real number from an exponential distribution with\n     *         rate {@code lambda}\n     * @throws IllegalArgumentException unless {@code lambda > 0.0}\n     */\n    public static double exponential(double lambda) {\n        if (!(lambda > 0.0))\n            throw new IllegalArgumentException(\"lambda must be positive: \" + lambda);\n        return -Math.log(1 - uniformDouble()) / lambda;\n    }\n\n    /**\n     * Returns a random real number from an exponential distribution\n     * with rate &lambda;.\n     *\n     * @param  lambda the rate of the exponential distribution\n     * @return a random real number from an exponential distribution with\n     *         rate {@code lambda}\n     * @throws IllegalArgumentException unless {@code lambda > 0.0}\n     * @deprecated Replaced by {@link #exponential(double)}.\n     */\n     @Deprecated\n    public static double exp(double lambda) {\n        return exponential(lambda);\n    }\n\n    /**\n     * Rearranges the elements of the specified array in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     */\n    public static void shuffle(Object[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            int r = i + uniformInt(n-i);     // between i and n-1\n            Object temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Rearranges the elements of the specified array in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     */\n    public static void shuffle(double[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            int r = i + uniformInt(n-i);     // between i and n-1\n            double temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Rearranges the elements of the specified array in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     */\n    public static void shuffle(int[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            int r = i + uniformInt(n-i);     // between i and n-1\n            int temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Rearranges the elements of the specified array in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     */\n    public static void shuffle(char[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            int r = i + uniformInt(n-i);     // between i and n-1\n            char temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Rearranges the elements of the specified subarray in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @param  lo the left endpoint (inclusive)\n     * @param  hi the right endpoint (exclusive)\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     *\n     */\n    public static void shuffle(Object[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        for (int i = lo; i < hi; i++) {\n            int r = i + uniformInt(hi-i);     // between i and hi-1\n            Object temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Rearranges the elements of the specified subarray in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @param  lo the left endpoint (inclusive)\n     * @param  hi the right endpoint (exclusive)\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static void shuffle(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        for (int i = lo; i < hi; i++) {\n            int r = i + uniformInt(hi-i);     // between i and hi-1\n            double temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Rearranges the elements of the specified subarray in uniformly random order.\n     *\n     * @param  a the array to shuffle\n     * @param  lo the left endpoint (inclusive)\n     * @param  hi the right endpoint (exclusive)\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static void shuffle(int[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        for (int i = lo; i < hi; i++) {\n            int r = i + uniformInt(hi-i);     // between i and hi-1\n            int temp = a[i];\n            a[i] = a[r];\n            a[r] = temp;\n        }\n    }\n\n    /**\n     * Returns a uniformly random permutation of <em>n</em> elements.\n     *\n     * @param  n number of elements\n     * @throws IllegalArgumentException if {@code n} is negative\n     * @return an array of length {@code n} that is a uniformly random permutation\n     *         of {@code 0}, {@code 1}, ..., {@code n-1}\n     */\n    public static int[] permutation(int n) {\n        if (n < 0) throw new IllegalArgumentException(\"n must be non-negative: \" + n);\n        int[] perm = new int[n];\n        for (int i = 0; i < n; i++)\n            perm[i] = i;\n        shuffle(perm);\n        return perm;\n    }\n\n    /**\n     * Returns a uniformly random permutation of <em>k</em> of <em>n</em> elements.\n     *\n     * @param  n number of elements\n     * @param  k number of elements to select\n     * @throws IllegalArgumentException if {@code n} is negative\n     * @throws IllegalArgumentException unless {@code 0 <= k <= n}\n     * @return an array of length {@code k} that is a uniformly random permutation\n     *         of {@code k} of the elements from {@code 0}, {@code 1}, ..., {@code n-1}\n     */\n    public static int[] permutation(int n, int k) {\n        if (n < 0) throw new IllegalArgumentException(\"n must be non-negative: \" + n);\n        if (k < 0 || k > n) throw new IllegalArgumentException(\"k must be between 0 and n: \" + k);\n        int[] perm = new int[k];\n        for (int i = 0; i < k; i++) {\n            int r = uniformInt(i+1);    // between 0 and i\n            perm[i] = perm[r];\n            perm[r] = i;\n        }\n        for (int i = k; i < n; i++) {\n            int r = uniformInt(i+1);    // between 0 and i\n            if (r < k) perm[r] = i;\n        }\n        return perm;\n    }\n\n    // throw an IllegalArgumentException if x is null\n    // (x can be of type Object[], double[], int[], ...)\n    private static void validateNotNull(Object x) {\n        if (x == null) {\n            throw new IllegalArgumentException(\"argument must not be null\");\n        }\n    }\n\n    // throw an exception unless 0 <= lo <= hi <= length\n    private static void validateSubarrayIndices(int lo, int hi, int length) {\n        if (lo < 0 || hi > length || lo > hi) {\n            throw new IllegalArgumentException(\"subarray indices out of bounds: [\" + lo + \", \" + hi + \")\");\n        }\n    }\n\n    /**\n     * Unit tests the methods in this class.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = Integer.parseInt(args[0]);\n        if (args.length == 2) StdRandom.setSeed(Long.parseLong(args[1]));\n        double[] probabilities = { 0.5, 0.3, 0.1, 0.1 };\n        int[] frequencies = { 5, 3, 1, 1 };\n        String[] a = \"A B C D E F G\".split(\" \");\n\n        StdOut.println(\"seed = \" + StdRandom.getSeed());\n        for (int i = 0; i < n; i++) {\n            StdOut.printf(\"%2d \",   uniformInt(100));\n            StdOut.printf(\"%8.5f \", uniformDouble(10.0, 99.0));\n            StdOut.printf(\"%5b \",   bernoulli(0.5));\n            StdOut.printf(\"%7.5f \", gaussian(9.0, 0.2));\n            StdOut.printf(\"%1d \",   discrete(probabilities));\n            StdOut.printf(\"%1d \",   discrete(frequencies));\n            StdOut.printf(\"%11d \",  uniformLong(100000000000L));\n            StdRandom.shuffle(a);\n            for (String s : a)\n                StdOut.print(s);\n            StdOut.println();\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StdStats.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StdStats.java\n *  Execution:    java StdStats < input.txt\n *  Dependencies: StdOut.java\n *\n *  Library of statistical functions.\n *\n *  The test client reads an array of real numbers from standard\n *  input, and computes the minimum, mean, maximum, and\n *  standard deviation.\n *\n *  The functions all throw a java.lang.IllegalArgumentException\n *  if the array passed in as an argument is null.\n *\n *  The floating-point functions all return NaN if any input is NaN.\n *\n *  Unlike Math.min() and Math.max(), the min() and max() functions\n *  do not differentiate between -0.0 and 0.0.\n *\n *  % more tiny.txt\n *  5\n *  3.0 1.0 2.0 5.0 4.0\n *\n *  % java StdStats < tiny.txt\n *         min   1.000\n *        mean   3.000\n *         max   5.000\n *     std dev   1.581\n *\n *  Should these functions use varargs instead of array arguments?\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code StdStats} class provides static methods for computing\n *  statistics such as min, max, mean, sample standard deviation, and\n *  sample variance.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://introcs.cs.princeton.edu/22library\">Section 2.2</a> of\n *  <i>Computer Science: An Interdisciplinary Approach</i>\n *  by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic final class StdStats {\n\n    private StdStats() { }\n\n    /**\n     * Returns the maximum value in the specified array.\n     *\n     * @param  a the array\n     * @return the maximum value in the array {@code a[]};\n     *         {@code Double.NEGATIVE_INFINITY} if no such value\n     */\n    public static double max(double[] a) {\n        validateNotNull(a);\n\n        double max = Double.NEGATIVE_INFINITY;\n        for (int i = 0; i < a.length; i++) {\n            if (Double.isNaN(a[i])) return Double.NaN;\n            if (a[i] > max) max = a[i];\n        }\n        return max;\n    }\n\n    /**\n     * Returns the maximum value in the specified subarray.\n     *\n     * @param  a the array\n     * @param  lo the left endpoint of the subarray (inclusive)\n     * @param  hi the right endpoint of the subarray (exclusive)\n     * @return the maximum value in the subarray {@code a[lo..hi)};\n     *         {@code Double.NEGATIVE_INFINITY} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double max(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        double max = Double.NEGATIVE_INFINITY;\n        for (int i = lo; i < hi; i++) {\n            if (Double.isNaN(a[i])) return Double.NaN;\n            if (a[i] > max) max = a[i];\n        }\n        return max;\n    }\n\n    /**\n     * Returns the maximum value in the specified array.\n     *\n     * @param  a the array\n     * @return the maximum value in the array {@code a[]};\n     *         {@code Integer.MIN_VALUE} if no such value\n     */\n    public static int max(int[] a) {\n        validateNotNull(a);\n\n        int max = Integer.MIN_VALUE;\n        for (int i = 0; i < a.length; i++) {\n            if (a[i] > max) max = a[i];\n        }\n        return max;\n    }\n\n    /**\n     * Returns the minimum value in the specified array.\n     *\n     * @param  a the array\n     * @return the minimum value in the array {@code a[]};\n     *         {@code Double.POSITIVE_INFINITY} if no such value\n     */\n    public static double min(double[] a) {\n        validateNotNull(a);\n\n        double min = Double.POSITIVE_INFINITY;\n        for (int i = 0; i < a.length; i++) {\n            if (Double.isNaN(a[i])) return Double.NaN;\n            if (a[i] < min) min = a[i];\n        }\n        return min;\n    }\n\n    /**\n     * Returns the minimum value in the specified subarray.\n     *\n     * @param  a the array\n     * @param  lo the left endpoint of the subarray (inclusive)\n     * @param  hi the right endpoint of the subarray (exclusive)\n     * @return the maximum value in the subarray {@code a[lo..hi)};\n     *         {@code Double.POSITIVE_INFINITY} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double min(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        double min = Double.POSITIVE_INFINITY;\n        for (int i = lo; i < hi; i++) {\n            if (Double.isNaN(a[i])) return Double.NaN;\n            if (a[i] < min) min = a[i];\n        }\n        return min;\n    }\n\n    /**\n     * Returns the minimum value in the specified array.\n     *\n     * @param  a the array\n     * @return the minimum value in the array {@code a[]};\n     *         {@code Integer.MAX_VALUE} if no such value\n     */\n    public static int min(int[] a) {\n        validateNotNull(a);\n\n        int min = Integer.MAX_VALUE;\n        for (int i = 0; i < a.length; i++) {\n            if (a[i] < min) min = a[i];\n        }\n        return min;\n    }\n\n    /**\n     * Returns the average value in the specified array.\n     *\n     * @param  a the array\n     * @return the average value in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double mean(double[] a) {\n        validateNotNull(a);\n\n        if (a.length == 0) return Double.NaN;\n        double sum = sum(a);\n        return sum / a.length;\n    }\n\n    /**\n     * Returns the average value in the specified subarray.\n     *\n     * @param a the array\n     * @param lo the left endpoint of the subarray (inclusive)\n     * @param hi the right endpoint of the subarray (exclusive)\n     * @return the average value in the subarray {@code a[lo..hi)};\n     *         {@code Double.NaN} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double mean(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        int length = hi - lo;\n        if (length == 0) return Double.NaN;\n\n        double sum = sum(a, lo, hi);\n        return sum / length;\n    }\n\n    /**\n     * Returns the average value in the specified array.\n     *\n     * @param  a the array\n     * @return the average value in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double mean(int[] a) {\n        validateNotNull(a);\n\n        if (a.length == 0) return Double.NaN;\n        int sum = sum(a);\n        return 1.0 * sum / a.length;\n    }\n\n    /**\n     * Returns the sample variance in the specified array.\n     *\n     * @param  a the array\n     * @return the sample variance in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double var(double[] a) {\n        validateNotNull(a);\n\n        if (a.length == 0) return Double.NaN;\n        double avg = mean(a);\n        double sum = 0.0;\n        for (int i = 0; i < a.length; i++) {\n            sum += (a[i] - avg) * (a[i] - avg);\n        }\n        return sum / (a.length - 1);\n    }\n\n    /**\n     * Returns the sample variance in the specified subarray.\n     *\n     * @param  a the array\n     * @param lo the left endpoint of the subarray (inclusive)\n     * @param hi the right endpoint of the subarray (exclusive)\n     * @return the sample variance in the subarray {@code a[lo..hi)};\n     *         {@code Double.NaN} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double var(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        int length = hi - lo;\n        if (length == 0) return Double.NaN;\n\n        double avg = mean(a, lo, hi);\n        double sum = 0.0;\n        for (int i = lo; i < hi; i++) {\n            sum += (a[i] - avg) * (a[i] - avg);\n        }\n        return sum / (length - 1);\n    }\n\n    /**\n     * Returns the sample variance in the specified array.\n     *\n     * @param  a the array\n     * @return the sample variance in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double var(int[] a) {\n        validateNotNull(a);\n        if (a.length == 0) return Double.NaN;\n        double avg = mean(a);\n        double sum = 0.0;\n        for (int i = 0; i < a.length; i++) {\n            sum += (a[i] - avg) * (a[i] - avg);\n        }\n        return sum / (a.length - 1);\n    }\n\n    /**\n     * Returns the population variance in the specified array.\n     *\n     * @param  a the array\n     * @return the population variance in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double varp(double[] a) {\n        validateNotNull(a);\n        if (a.length == 0) return Double.NaN;\n        double avg = mean(a);\n        double sum = 0.0;\n        for (int i = 0; i < a.length; i++) {\n            sum += (a[i] - avg) * (a[i] - avg);\n        }\n        return sum / a.length;\n    }\n\n    /**\n     * Returns the population variance in the specified subarray.\n     *\n     * @param  a the array\n     * @param lo the left endpoint of the subarray (inclusive)\n     * @param hi the right endpoint of the subarray (exclusive)\n     * @return the population variance in the subarray {@code a[lo..hi)};\n     *         {@code Double.NaN} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double varp(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        int length = hi - lo;\n        if (length == 0) return Double.NaN;\n\n        double avg = mean(a, lo, hi);\n        double sum = 0.0;\n        for (int i = lo; i < hi; i++) {\n            sum += (a[i] - avg) * (a[i] - avg);\n        }\n        return sum / length;\n    }\n\n    /**\n     * Returns the sample standard deviation in the specified array.\n     *\n     * @param  a the array\n     * @return the sample standard deviation in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double stddev(double[] a) {\n        validateNotNull(a);\n        return Math.sqrt(var(a));\n    }\n\n    /**\n     * Returns the sample standard deviation in the specified array.\n     *\n     * @param  a the array\n     * @return the sample standard deviation in the array {@code a[]};\n     *         {@code Double.NaN} if no such value\n     */\n    public static double stddev(int[] a) {\n        validateNotNull(a);\n        return Math.sqrt(var(a));\n    }\n\n    /**\n     * Returns the sample standard deviation in the specified subarray.\n     *\n     * @param  a the array\n     * @param lo the left endpoint of the subarray (inclusive)\n     * @param hi the right endpoint of the subarray (exclusive)\n     * @return the sample standard deviation in the subarray {@code a[lo..hi)};\n     *         {@code Double.NaN} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double stddev(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        return Math.sqrt(var(a, lo, hi));\n    }\n\n\n    /**\n     * Returns the population standard deviation in the specified array.\n     *\n     * @param  a the array\n     * @return the population standard deviation in the array;\n     *         {@code Double.NaN} if no such value\n     */\n    public static double stddevp(double[] a) {\n        validateNotNull(a);\n        return Math.sqrt(varp(a));\n    }\n\n    /**\n     * Returns the population standard deviation in the specified subarray.\n     *\n     * @param  a the array\n     * @param lo the left endpoint of the subarray (inclusive)\n     * @param hi the right endpoint of the subarray (exclusive)\n     * @return the population standard deviation in the subarray {@code a[lo..hi)};\n     *         {@code Double.NaN} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    public static double stddevp(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        return Math.sqrt(varp(a, lo, hi));\n    }\n\n    /**\n     * Returns the sum of all values in the specified array.\n     *\n     * @param  a the array\n     * @return the sum of all values in the array {@code a[]};\n     *         {@code 0.0} if no such value\n     */\n    private static double sum(double[] a) {\n        validateNotNull(a);\n        double sum = 0.0;\n        for (int i = 0; i < a.length; i++) {\n            sum += a[i];\n        }\n        return sum;\n    }\n\n    /**\n     * Returns the sum of all values in the specified subarray.\n     *\n     * @param  a the array\n     * @param lo the left endpoint of the subarray (inclusive)\n     * @param hi the right endpoint of the subarray (exclusive)\n     * @return the sum of all values in the subarray {@code a[lo..hi)};\n     *         {@code 0.0} if no such value\n     * @throws IllegalArgumentException if {@code a} is {@code null}\n     * @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}\n     */\n    private static double sum(double[] a, int lo, int hi) {\n        validateNotNull(a);\n        validateSubarrayIndices(lo, hi, a.length);\n\n        double sum = 0.0;\n        for (int i = lo; i < hi; i++) {\n            sum += a[i];\n        }\n        return sum;\n    }\n\n    /**\n     * Returns the sum of all values in the specified array.\n     *\n     * @param  a the array\n     * @return the sum of all values in the array {@code a[]};\n     *         {@code 0.0} if no such value\n     */\n    private static int sum(int[] a) {\n        validateNotNull(a);\n        int sum = 0;\n        for (int i = 0; i < a.length; i++) {\n            sum += a[i];\n        }\n        return sum;\n    }\n\n   /**\n     * Plots the points (0, <em>a</em><sub>0</sub>), (1, <em>a</em><sub>1</sub>), ...,\n     * (<em>n</em>-1, <em>a</em><sub><em>n</em>-1</sub>) to standard draw.\n     *\n     * @param a the array of values\n     */\n    public static void plotPoints(double[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        StdDraw.setXscale(-1, n);\n        StdDraw.setPenRadius(1.0 / (3.0 * n));\n        for (int i = 0; i < n; i++) {\n            StdDraw.point(i, a[i]);\n        }\n    }\n\n   /**\n     * Plots the line segments connecting\n     * (<em>i</em>, <em>a</em><sub><em>i</em></sub>) to\n     * (<em>i</em>+1, <em>a</em><sub><em>i</em>+1</sub>) for\n     * each <em>i</em> to standard draw.\n     *\n     * @param a the array of values\n     */\n    public static void plotLines(double[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        StdDraw.setXscale(-1, n);\n        StdDraw.setPenRadius();\n        for (int i = 1; i < n; i++) {\n            StdDraw.line(i-1, a[i-1], i, a[i]);\n        }\n    }\n\n   /**\n     * Plots bars from (0, <em>a</em><sub><em>i</em></sub>) to\n     * (<em>a</em><sub><em>i</em></sub>) for each <em>i</em>\n     * to standard draw.\n     *\n     * @param a the array of values\n     */\n    public static void plotBars(double[] a) {\n        validateNotNull(a);\n        int n = a.length;\n        StdDraw.setXscale(-1, n);\n        for (int i = 0; i < n; i++) {\n            StdDraw.filledRectangle(i, a[i]/2, 0.25, a[i]/2);\n        }\n    }\n\n    // throw an IllegalArgumentException if x is null\n    // (x is either of type double[] or int[])\n    private static void validateNotNull(Object x) {\n        if (x == null)\n            throw new IllegalArgumentException(\"argument is null\");\n    }\n\n    // throw an exception unless 0 <= lo <= hi <= length\n    private static void validateSubarrayIndices(int lo, int hi, int length) {\n        if (lo < 0 || hi > length || lo > hi)\n            throw new IllegalArgumentException(\"subarray indices out of bounds: [\" + lo + \", \" + hi + \")\");\n    }\n\n\n   /**\n     * Unit tests {@code StdStats}.\n     * Convert command-line arguments to array of doubles and call various methods.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        double[] a = StdArrayIO.readDouble1D();\n        StdOut.printf(\"       min %10.3f\\n\", min(a));\n        StdOut.printf(\"      mean %10.3f\\n\", mean(a));\n        StdOut.printf(\"       max %10.3f\\n\", max(a));\n        StdOut.printf(\"    stddev %10.3f\\n\", stddev(a));\n        StdOut.printf(\"       var %10.3f\\n\", var(a));\n        StdOut.printf(\"   stddevp %10.3f\\n\", stddevp(a));\n        StdOut.printf(\"      varp %10.3f\\n\", varp(a));\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Stopwatch.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Stopwatch.java\n *  Execution:    java Stopwatch n\n *  Dependencies: none\n *\n *  A utility class to measure the running time (wall clock) of a program.\n *\n *  % java8 Stopwatch 100000000\n *  6.666667e+11  0.5820 seconds\n *  6.666667e+11  8.4530 seconds\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Stopwatch} data type is for measuring\n *  the time that elapses between the start and end of a\n *  programming task (wall-clock time).\n *\n *  To measure the running time of a code fragment, construct a\n *  <code>Stopwatch</code> object, execute the code you want to time,\n *  and then call the <code>elapsedTime()</code> method to get the\n *  elapsed time in seconds.\n *  <pre>\n *\n *   Stopwatch stopwatch = new Stopwatch();\n *\n *   // do some computationally intensive calculation here\n *\n *   double time = stopwatch.elapsedTime();\n *  </pre>\n *  <p>\n *\n *  See {@link StopwatchCPU} for a version that measures CPU time.\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/14analysis\">Section 1.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\n\npublic class Stopwatch {\n\n    private final long start;\n\n    /**\n     * Initializes a new stopwatch.\n     */\n    public Stopwatch() {\n        start = System.currentTimeMillis();\n    }\n\n\n    /**\n     * Returns the elapsed CPU time (in seconds) since the stopwatch was created.\n     *\n     * @return elapsed CPU time (in seconds) since the stopwatch was created\n     */\n    public double elapsedTime() {\n        long now = System.currentTimeMillis();\n        return (now - start) / 1000.0;\n    }\n\n\n    /**\n     * Unit tests the {@code Stopwatch} data type.\n     * Takes a command-line argument {@code n} and computes the\n     * sum of the square roots of the first {@code n} positive integers,\n     * first using {@code Math.sqrt()}, then using {@code Math.pow()}.\n     * It prints to standard output the sum and the amount of time to\n     * compute the sum. Note that the discrete sum can be approximated by\n     * an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = Integer.parseInt(args[0]);\n\n        // sum of square roots of integers from 1 to n using Math.sqrt(x).\n        Stopwatch timer1 = new Stopwatch();\n        double sum1 = 0.0;\n        for (int i = 1; i <= n; i++) {\n            sum1 += Math.sqrt(i);\n        }\n        double time1 = timer1.elapsedTime();\n        StdOut.printf(\"%e (%.2f seconds)\\n\", sum1, time1);\n\n        // sum of square roots of integers from 1 to n using Math.pow(x, 0.5).\n        Stopwatch timer2 = new Stopwatch();\n        double sum2 = 0.0;\n        for (int i = 1; i <= n; i++) {\n            sum2 += Math.pow(i, 0.5);\n        }\n        double time2 = timer2.elapsedTime();\n        StdOut.printf(\"%e (%.2f seconds)\\n\", sum2, time2);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/StopwatchCPU.java",
    "content": "/******************************************************************************\n *  Compilation:  javac StopwatchCPU.java\n *  Execution:    java StopwatchCPU n\n *  Dependencies: none\n *\n *  A version of Stopwatch.java that measures CPU time on a single\n *  core or processor (instead of wall clock time).\n *\n *  % java8 StopwatchCPU 100000000\n *  6.666667e+11 (1.05 seconds)\n *  6.666667e+11 (7.50 seconds)\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.lang.management.ThreadMXBean;\nimport java.lang.management.ManagementFactory;\n\n/**\n *  The {@code StopwatchCPU} data type is for measuring\n *  the CPU time used during a programming task.\n *\n *  See {@link Stopwatch} for a version that measures wall-clock time\n *  (the real time that elapses).\n *\n *  @author Josh Hug\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class StopwatchCPU {\n    private static final double NANOSECONDS_PER_SECOND = 1000000000;\n\n    private final ThreadMXBean threadTimer;\n    private final long start;\n\n    /**\n     * Initializes a new stopwatch.\n     */\n    public StopwatchCPU() {\n        threadTimer = ManagementFactory.getThreadMXBean();\n        start = threadTimer.getCurrentThreadCpuTime();\n    }\n\n    /**\n     * Returns the elapsed CPU time (in seconds) since the stopwatch was created.\n     *\n     * @return elapsed CPU time (in seconds) since the stopwatch was created\n     */\n    public double elapsedTime() {\n        long now = threadTimer.getCurrentThreadCpuTime();\n        return (now - start) / NANOSECONDS_PER_SECOND;\n    }\n\n    /**\n     * Unit tests the {@code StopwatchCPU} data type.\n     * Takes a command-line argument {@code n} and computes the\n     * sum of the square roots of the first {@code n} positive integers,\n     * first using {@code Math.sqrt()}, then using {@code Math.pow()}.\n     * It prints to standard output the sum and the amount of time to\n     * compute the sum. Note that the discrete sum can be approximated by\n     * an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = Integer.parseInt(args[0]);\n\n        // sum of square roots of integers from 1 to n using Math.sqrt(x).\n        StopwatchCPU timer1 = new StopwatchCPU();\n        double sum1 = 0.0;\n        for (int i = 1; i <= n; i++) {\n            sum1 += Math.sqrt(i);\n        }\n        double time1 = timer1.elapsedTime();\n        StdOut.printf(\"%e (%.2f seconds)\\n\", sum1, time1);\n\n        // sum of square roots of integers from 1 to n using Math.pow(x, 0.5).\n        StopwatchCPU timer2 = new StopwatchCPU();\n        double sum2 = 0.0;\n        for (int i = 1; i <= n; i++) {\n            sum2 += Math.pow(i, 0.5);\n        }\n        double time2 = timer2.elapsedTime();\n        StdOut.printf(\"%e (%.2f seconds)\\n\", sum2, time2);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SuffixArray.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SuffixArray.java\n *  Execution:    java SuffixArray < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/63suffix/abra.txt\n *\n *  A data type that computes the suffix array of a string.\n *\n *   % java SuffixArray < abra.txt\n *    i ind lcp rnk  select\n *   ---------------------------\n *    0  11   -   0  \"!\"\n *    1  10   0   1  \"A!\"\n *    2   7   1   2  \"ABRA!\"\n *    3   0   4   3  \"ABRACADABRA!\"\n *    4   3   1   4  \"ACADABRA!\"\n *    5   5   1   5  \"ADABRA!\"\n *    6   8   0   6  \"BRA!\"\n *    7   1   3   7  \"BRACADABRA!\"\n *    8   4   0   8  \"CADABRA!\"\n *    9   6   0   9  \"DABRA!\"\n *   10   9   0  10  \"RA!\"\n *   11   2   2  11  \"RACADABRA!\"\n *\n *  See SuffixArrayX.java for an optimized version that uses 3-way\n *  radix quicksort and does not use the nested class Suffix.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n *  The {@code SuffixArray} class represents a suffix array of a string of\n *  length <em>n</em>.\n *  It supports the <em>selecting</em> the <em>i</em>th smallest suffix,\n *  getting the <em>index</em> of the <em>i</em>th smallest suffix,\n *  computing the length of the <em>longest common prefix</em> between the\n *  <em>i</em>th smallest suffix and the <em>i</em>-1st smallest suffix,\n *  and determining the <em>rank</em> of a query string (which is the number\n *  of suffixes strictly less than the query string).\n *  <p>\n *  This implementation uses a nested class {@code Suffix} to represent\n *  a suffix of a string (using constant time and space) and\n *  {@code Arrays.sort()} to sort the array of suffixes.\n *  The <em>index</em> and <em>length</em> operations takes constant time\n *  in the worst case. The <em>lcp</em> operation takes time proportional to the\n *  length of the longest common prefix.\n *  The <em>select</em> operation takes time proportional\n *  to the length of the suffix and should be used primarily for debugging.\n *  <p>\n *  For alternate implementations of the same API, see\n *  {@link SuffixArrayX}, which is faster in practice (uses 3-way radix quicksort)\n *  and uses less memory (does not create {@code Suffix} objects)\n *  and <a href = \"https://algs4.cs.princeton.edu/63suffix/SuffixArrayJava6.java.html\">SuffixArrayJava6.java</a>,\n *  which relies on the constant-time substring extraction method that existed\n *  in Java 6.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/63suffix\">Section 6.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class SuffixArray {\n    private Suffix[] suffixes;\n\n    /**\n     * Initializes a suffix array for the given {@code text} string.\n     * @param text the input string\n     */\n    public SuffixArray(String text) {\n        int n = text.length();\n        this.suffixes = new Suffix[n];\n        for (int i = 0; i < n; i++)\n            suffixes[i] = new Suffix(text, i);\n        Arrays.sort(suffixes);\n    }\n\n    private static class Suffix implements Comparable<Suffix> {\n        private final String text;\n        private final int index;\n\n        private Suffix(String text, int index) {\n            this.text = text;\n            this.index = index;\n        }\n        private int length() {\n            return text.length() - index;\n        }\n        private char charAt(int i) {\n            return text.charAt(index + i);\n        }\n\n        public int compareTo(Suffix that) {\n            if (this == that) return 0;  // optimization\n            int n = Math.min(this.length(), that.length());\n            for (int i = 0; i < n; i++) {\n                if (this.charAt(i) < that.charAt(i)) return -1;\n                if (this.charAt(i) > that.charAt(i)) return +1;\n            }\n            return this.length() - that.length();\n        }\n\n        public String toString() {\n            return text.substring(index);\n        }\n    }\n\n    /**\n     * Returns the length of the input string.\n     * @return the length of the input string\n     */\n    public int length() {\n        return suffixes.length;\n    }\n\n\n    /**\n     * Returns the index into the original string of the <em>i</em>th smallest suffix.\n     * That is, {@code text.substring(sa.index(i))} is the <em>i</em>th smallest suffix.\n     * @param i an integer between 0 and <em>n</em>-1\n     * @return the index into the original string of the <em>i</em>th smallest suffix\n     * @throws java.lang.IllegalArgumentException unless {@code 0 <= i < n}\n     */\n    public int index(int i) {\n        if (i < 0 || i >= suffixes.length) throw new IllegalArgumentException();\n        return suffixes[i].index;\n    }\n\n\n    /**\n     * Returns the length of the longest common prefix of the <em>i</em>th\n     * smallest suffix and the <em>i</em>-1st smallest suffix.\n     * @param i an integer between 1 and <em>n</em>-1\n     * @return the length of the longest common prefix of the <em>i</em>th\n     * smallest suffix and the <em>i</em>-1st smallest suffix.\n     * @throws java.lang.IllegalArgumentException unless {@code 1 <= i < n}\n     */\n    public int lcp(int i) {\n        if (i < 1 || i >= suffixes.length) throw new IllegalArgumentException();\n        return lcpSuffix(suffixes[i], suffixes[i-1]);\n    }\n\n    // longest common prefix of s and t\n    private static int lcpSuffix(Suffix s, Suffix t) {\n        int n = Math.min(s.length(), t.length());\n        for (int i = 0; i < n; i++) {\n            if (s.charAt(i) != t.charAt(i)) return i;\n        }\n        return n;\n    }\n\n    /**\n     * Returns the <em>i</em>th smallest suffix as a string.\n     * @param i the index\n     * @return the <em>i</em> smallest suffix as a string\n     * @throws java.lang.IllegalArgumentException unless {@code 0 <= i < n}\n     */\n    public String select(int i) {\n        if (i < 0 || i >= suffixes.length) throw new IllegalArgumentException();\n        return suffixes[i].toString();\n    }\n\n    /**\n     * Returns the number of suffixes strictly less than the {@code query} string.\n     * We note that {@code rank(select(i))} equals {@code i} for each {@code i}\n     * between 0 and <em>n</em>-1.\n     * @param query the query string\n     * @return the number of suffixes strictly less than {@code query}\n     */\n    public int rank(String query) {\n        int lo = 0, hi = suffixes.length - 1;\n        while (lo <= hi) {\n            int mid = lo + (hi - lo) / 2;\n            int cmp = compare(query, suffixes[mid]);\n            if (cmp < 0) hi = mid - 1;\n            else if (cmp > 0) lo = mid + 1;\n            else return mid;\n        }\n        return lo;\n    }\n\n    // compare query string to suffix\n    private static int compare(String query, Suffix suffix) {\n        int n = Math.min(query.length(), suffix.length());\n        for (int i = 0; i < n; i++) {\n            if (query.charAt(i) < suffix.charAt(i)) return -1;\n            if (query.charAt(i) > suffix.charAt(i)) return +1;\n        }\n        return query.length() - suffix.length();\n    }\n\n    /**\n     * Unit tests the {@code SuffixArray} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String s = StdIn.readAll().replaceAll(\"\\\\s+\", \" \").trim();\n        SuffixArray suffix = new SuffixArray(s);\n\n        // StdOut.println(\"rank(\" + args[0] + \") = \" + suffix.rank(args[0]));\n\n        StdOut.println(\"  i ind lcp rnk select\");\n        StdOut.println(\"---------------------------\");\n\n        for (int i = 0; i < s.length(); i++) {\n            int index = suffix.index(i);\n            String ith = \"\\\"\" + s.substring(index, Math.min(index + 50, s.length())) + \"\\\"\";\n            assert s.substring(index).equals(suffix.select(i));\n            int rank = suffix.rank(s.substring(index));\n            if (i == 0) {\n                StdOut.printf(\"%3d %3d %3s %3d %s\\n\", i, index, \"-\", rank, ith);\n            }\n            else {\n                int lcp = suffix.lcp(i);\n                StdOut.printf(\"%3d %3d %3d %3d %s\\n\", i, index, lcp, rank, ith);\n            }\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SuffixArrayX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SuffixArrayX.java\n *  Execution:    java SuffixArrayX < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/63suffix/abra.txt\n *\n *  A data type that computes the suffix array of a string using 3-way\n *  radix quicksort.\n *\n *  % java SuffixArrayX < abra.txt\n *    i ind lcp rnk  select\n *  ---------------------------\n *    0  11   -   0  !\n *    1  10   0   1  A!\n *    2   7   1   2  ABRA!\n *    3   0   4   3  ABRACADABRA!\n *    4   3   1   4  ACADABRA!\n *    5   5   1   5  ADABRA!\n *    6   8   0   6  BRA!\n *    7   1   3   7  BRACADABRA!\n *    8   4   0   8  CADABRA!\n *    9   6   0   9  DABRA!\n *   10   9   0  10  RA!\n *   11   2   2  11  RACADABRA!\n *\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code SuffixArrayX} class represents a suffix array of a string of\n *  length <em>n</em>.\n *  It supports the <em>selecting</em> the <em>i</em>th smallest suffix,\n *  getting the <em>index</em> of the <em>i</em>th smallest suffix,\n *  computing the length of the <em>longest common prefix</em> between the\n *  <em>i</em>th smallest suffix and the <em>i</em>-1st smallest suffix,\n *  and determining the <em>rank</em> of a query string (which is the number\n *  of suffixes strictly less than the query string).\n *  <p>\n *  This implementation uses 3-way radix quicksort to sort the array of suffixes.\n *  For a simpler (but less efficient) implementations of the same API, see\n *  {@link SuffixArray}.\n *  The <em>index</em> and <em>length</em> operations takes constant time\n *  in the worst case. The <em>lcp</em> operation takes time proportional to the\n *  length of the longest common prefix.\n *  The <em>select</em> operation takes time proportional\n *  to the length of the suffix and should be used primarily for debugging.\n *  <p>\n *  This implementation uses '\\0' as a sentinel and assumes that the character\n *  '\\0' does not appear in the text.\n *  <p>\n *  In practice, this algorithm runs very fast. However, in the worst-case\n *  it can be very poor (e.g., a string consisting of N copies of the same\n *  character). We do not shuffle the array of suffixes before sorting because\n *  shuffling is relatively expensive and a pathological input for which\n *  the suffixes start out in a bad order (e.g., sorted) is likely to be\n *  a bad input for this algorithm with or without the shuffle.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/63suffix\">Section 6.3</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class SuffixArrayX {\n    private static final int CUTOFF =  5;   // cutoff to insertion sort (any value between 0 and 12)\n\n    private final char[] text;\n    private final int[] index;   // index[i] = j means text.substring(j) is ith largest suffix\n    private final int n;         // number of characters in text\n\n    /**\n     * Initializes a suffix array for the given {@code text} string.\n     * @param text the input string\n     */\n    public SuffixArrayX(String text) {\n        n = text.length();\n        text = text + '\\0';\n        this.text = text.toCharArray();\n        this.index = new int[n];\n        for (int i = 0; i < n; i++)\n            index[i] = i;\n\n        sort(0, n-1, 0);\n    }\n\n    // 3-way string quicksort lo..hi starting at dth character\n    private void sort(int lo, int hi, int d) {\n\n        // cutoff to insertion sort for small subarrays\n        if (hi <= lo + CUTOFF) {\n            insertion(lo, hi, d);\n            return;\n        }\n\n        int lt = lo, gt = hi;\n        char v = text[index[lo] + d];\n        int i = lo + 1;\n        while (i <= gt) {\n            char t = text[index[i] + d];\n            if      (t < v) exch(lt++, i++);\n            else if (t > v) exch(i, gt--);\n            else            i++;\n        }\n\n        // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].\n        sort(lo, lt-1, d);\n        if (v > 0) sort(lt, gt, d+1);\n        sort(gt+1, hi, d);\n    }\n\n    // sort from a[lo] to a[hi], starting at the dth character\n    private void insertion(int lo, int hi, int d) {\n        for (int i = lo; i <= hi; i++)\n            for (int j = i; j > lo && less(index[j], index[j-1], d); j--)\n                exch(j, j-1);\n    }\n\n    // is text[i+d..n) < text[j+d..n) ?\n    private boolean less(int i, int j, int d) {\n        if (i == j) return false;\n        i = i + d;\n        j = j + d;\n        while (i < n && j < n) {\n            if (text[i] < text[j]) return true;\n            if (text[i] > text[j]) return false;\n            i++;\n            j++;\n        }\n        return i > j;\n    }\n\n    // exchange index[i] and index[j]\n    private void exch(int i, int j) {\n        int swap = index[i];\n        index[i] = index[j];\n        index[j] = swap;\n    }\n\n    /**\n     * Returns the length of the input string.\n     * @return the length of the input string\n     */\n    public int length() {\n        return n;\n    }\n\n\n    /**\n     * Returns the index into the original string of the <em>i</em>th smallest suffix.\n     * That is, {@code text.substring(sa.index(i))} is the <em>i</em> smallest suffix.\n     * @param i an integer between 0 and <em>n</em>-1\n     * @return the index into the original string of the <em>i</em>th smallest suffix\n     * @throws java.lang.IllegalArgumentException unless {@code 0 <=i < n}\n     */\n    public int index(int i) {\n        if (i < 0 || i >= n) throw new IllegalArgumentException();\n        return index[i];\n    }\n\n    /**\n     * Returns the length of the longest common prefix of the <em>i</em>th\n     * smallest suffix and the <em>i</em>-1st smallest suffix.\n     * @param i an integer between 1 and <em>n</em>-1\n     * @return the length of the longest common prefix of the <em>i</em>th\n     * smallest suffix and the <em>i</em>-1st smallest suffix.\n     * @throws java.lang.IllegalArgumentException unless {@code 1 <= i < n}\n     */\n    public int lcp(int i) {\n        if (i < 1 || i >= n) throw new IllegalArgumentException();\n        return lcp(index[i], index[i-1]);\n    }\n\n    // longest common prefix of text[i..n) and text[j..n)\n    private int lcp(int i, int j) {\n        int length = 0;\n        while (i < n && j < n) {\n            if (text[i] != text[j]) return length;\n            i++;\n            j++;\n            length++;\n        }\n        return length;\n    }\n\n    /**\n     * Returns the <em>i</em>th smallest suffix as a string.\n     * @param i the index\n     * @return the <em>i</em> smallest suffix as a string\n     * @throws java.lang.IllegalArgumentException unless {@code 0 <= i < n}\n     */\n    public String select(int i) {\n        if (i < 0 || i >= n) throw new IllegalArgumentException();\n        return new String(text, index[i], n - index[i]);\n    }\n\n    /**\n     * Returns the number of suffixes strictly less than the {@code query} string.\n     * We note that {@code rank(select(i))} equals {@code i} for each {@code i}\n     * between 0 and <em>n</em>-1.\n     * @param query the query string\n     * @return the number of suffixes strictly less than {@code query}\n     */\n    public int rank(String query) {\n        int lo = 0, hi = n - 1;\n        while (lo <= hi) {\n            int mid = lo + (hi - lo) / 2;\n            int cmp = compare(query, index[mid]);\n            if      (cmp < 0) hi = mid - 1;\n            else if (cmp > 0) lo = mid + 1;\n            else return mid;\n        }\n        return lo;\n    }\n\n    // is query < text[i..n) ?\n    private int compare(String query, int i) {\n        int m = query.length();\n        int j = 0;\n        while (i < n && j < m) {\n            if (query.charAt(j) != text[i]) return query.charAt(j) - text[i];\n            i++;\n            j++;\n\n        }\n        if (i < n) return -1;\n        if (j < m) return +1;\n        return 0;\n    }\n\n\n    /**\n     * Unit tests the {@code SuffixArrayX} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String s = StdIn.readAll().replaceAll(\"\\n\", \" \").trim();\n        SuffixArrayX suffix1 = new SuffixArrayX(s);\n        SuffixArray suffix2 = new SuffixArray(s);\n        boolean check = true;\n        for (int i = 0; check && i < s.length(); i++) {\n            if (suffix1.index(i) != suffix2.index(i)) {\n                StdOut.println(\"suffix1(\" + i + \") = \" + suffix1.index(i));\n                StdOut.println(\"suffix2(\" + i + \") = \" + suffix2.index(i));\n                String ith = \"\\\"\" + s.substring(suffix1.index(i), Math.min(suffix1.index(i) + 50, s.length())) + \"\\\"\";\n                String jth = \"\\\"\" + s.substring(suffix2.index(i), Math.min(suffix2.index(i) + 50, s.length())) + \"\\\"\";\n                StdOut.println(ith);\n                StdOut.println(jth);\n                check = false;\n            }\n        }\n\n        StdOut.println(\"  i ind lcp rnk  select\");\n        StdOut.println(\"---------------------------\");\n\n        for (int i = 0; i < s.length(); i++) {\n            int index = suffix2.index(i);\n            String ith = \"\\\"\" + s.substring(index, Math.min(index + 50, s.length())) + \"\\\"\";\n            int rank = suffix2.rank(s.substring(index));\n            assert s.substring(index).equals(suffix2.select(i));\n            if (i == 0) {\n                StdOut.printf(\"%3d %3d %3s %3d  %s\\n\", i, index, \"-\", rank, ith);\n            }\n            else {\n                // int lcp  = suffix.lcp(suffix2.index(i), suffix2.index(i-1));\n                int lcp  = suffix2.lcp(i);\n                StdOut.printf(\"%3d %3d %3d %3d  %s\\n\", i, index, lcp, rank, ith);\n            }\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SymbolDigraph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SymbolDigraph.java\n *  Execution:    java SymbolDigraph\n *  Dependencies: ST.java Digraph.java In.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/routes.txt\n *\n *  %  java SymbolDigraph routes.txt \" \"\n *  JFK\n *     MCO\n *     ATL\n *     ORD\n *  ATL\n *     HOU\n *     MCO\n *  LAX\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code SymbolDigraph} class represents a digraph, where the\n *  vertex names are arbitrary strings.\n *  By providing mappings between string vertex names and integers,\n *  it serves as a wrapper around the\n *  {@link Digraph} data type, which assumes the vertex names are integers\n *  between 0 and <em>V</em> - 1.\n *  It also supports initializing a symbol digraph from a file.\n *  <p>\n *  This implementation uses an {@link ST} to map from strings to integers,\n *  an array to map from integers to strings, and a {@link Digraph} to store\n *  the underlying graph.\n *  The <em>indexOf</em> and <em>contains</em> operations take time\n *  proportional to log <em>V</em>, where <em>V</em> is the number of vertices.\n *  The <em>nameOf</em> operation takes constant time.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class SymbolDigraph {\n    private ST<String, Integer> st;  // string -> index\n    private String[] keys;           // index  -> string\n    private Digraph digraph;         // the underlying digraph\n\n    /**\n     * Initializes a digraph from a file using the specified delimiter.\n     * Each line in the file contains\n     * the name of a vertex, followed by a list of the names\n     * of the vertices adjacent to that vertex, separated by the delimiter.\n     * @param filename the name of the file\n     * @param delimiter the delimiter between fields\n     */\n    public SymbolDigraph(String filename, String delimiter) {\n        st = new ST<String, Integer>();\n\n        // First pass builds the index by reading strings to associate\n        // distinct strings with an index\n        In in = new In(filename);\n        while (in.hasNextLine()) {\n            String[] a = in.readLine().split(delimiter);\n            for (int i = 0; i < a.length; i++) {\n                if (!st.contains(a[i]))\n                    st.put(a[i], st.size());\n            }\n        }\n\n        // inverted index to get string keys in an array\n        keys = new String[st.size()];\n        for (String name : st.keys()) {\n            keys[st.get(name)] = name;\n        }\n\n        // second pass builds the digraph by connecting first vertex on each\n        // line to all others\n        digraph = new Digraph(st.size());\n        in = new In(filename);\n        while (in.hasNextLine()) {\n            String[] a = in.readLine().split(delimiter);\n            int v = st.get(a[0]);\n            for (int i = 1; i < a.length; i++) {\n                int w = st.get(a[i]);\n                digraph.addEdge(v, w);\n            }\n        }\n    }\n\n    /**\n     * Does the digraph contain the vertex named {@code s}?\n     * @param s the name of a vertex\n     * @return {@code true} if {@code s} is the name of a vertex, and {@code false} otherwise\n     */\n    public boolean contains(String s) {\n        return st.contains(s);\n    }\n\n    /**\n     * Returns the integer associated with the vertex named {@code s}.\n     * @param s the name of a vertex\n     * @return the integer (between 0 and <em>V</em> - 1) associated with the vertex named {@code s}\n     * @deprecated Replaced by {@link #indexOf(String)}.\n     */\n    @Deprecated\n    public int index(String s) {\n        return st.get(s);\n    }\n\n    /**\n     * Returns the integer associated with the vertex named {@code s}.\n     * @param s the name of a vertex\n     * @return the integer (between 0 and <em>V</em> - 1) associated with the vertex named {@code s}\n     */\n    public int indexOf(String s) {\n        return st.get(s);\n    }\n\n    /**\n     * Returns the name of the vertex associated with the integer {@code v}.\n     * @param  v the integer corresponding to a vertex (between 0 and <em>V</em> - 1)\n     * @return the name of the vertex associated with the integer {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @deprecated Replaced by {@link #nameOf(int)}.\n     */\n    @Deprecated\n    public String name(int v) {\n        validateVertex(v);\n        return keys[v];\n    }\n\n    /**\n     * Returns the name of the vertex associated with the integer {@code v}.\n     * @param  v the integer corresponding to a vertex (between 0 and <em>V</em> - 1)\n     * @return the name of the vertex associated with the integer {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public String nameOf(int v) {\n        validateVertex(v);\n        return keys[v];\n    }\n\n    /**\n     * Returns the digraph associated with the symbol graph. It is the client's responsibility\n     * not to mutate the digraph.\n     *\n     * @return the digraph associated with the symbol digraph\n     * @deprecated Replaced by {@link #digraph()}.\n     */\n    @Deprecated\n    public Digraph G() {\n        return digraph;\n    }\n\n    /**\n     * Returns the digraph associated with the symbol graph. It is the client's responsibility\n     * not to mutate the digraph.\n     *\n     * @return the digraph associated with the symbol digraph\n     */\n    public Digraph digraph() {\n        return digraph;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = digraph.V();\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code SymbolDigraph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String filename  = args[0];\n        String delimiter = args[1];\n        SymbolDigraph sg = new SymbolDigraph(filename, delimiter);\n        Digraph digraph = sg.digraph();\n        while (!StdIn.isEmpty()) {\n            String t = StdIn.readLine();\n            for (int v : digraph.adj(sg.index(t))) {\n                StdOut.println(\"   \" + sg.nameOf(v));\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/SymbolGraph.java",
    "content": "/******************************************************************************\n *  Compilation:  javac SymbolGraph.java\n *  Execution:    java SymbolGraph filename.txt delimiter\n *  Dependencies: ST.java Graph.java In.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/41graph/routes.txt\n *                https://algs4.cs.princeton.edu/41graph/movies.txt\n *                https://algs4.cs.princeton.edu/41graph/moviestiny.txt\n *                https://algs4.cs.princeton.edu/41graph/moviesG.txt\n *                https://algs4.cs.princeton.edu/41graph/moviestopGrossing.txt\n *\n *  %  java SymbolGraph routes.txt \" \"\n *  JFK\n *     MCO\n *     ATL\n *     ORD\n *  LAX\n *     PHX\n *     LAS\n *\n *  % java SymbolGraph movies.txt \"/\"\n *  Tin Men (1987)\n *     Hershey, Barbara\n *     Geppi, Cindy\n *     Jones, Kathy (II)\n *     Herr, Marcia\n *     ...\n *     Blumenfeld, Alan\n *     DeBoy, David\n *  Bacon, Kevin\n *     Woodsman, The (2004)\n *     Wild Things (1998)\n *     Where the Truth Lies (2005)\n *     Tremors (1990)\n *     ...\n *     Apollo 13 (1995)\n *     Animal House (1978)\n *\n *\n *  Assumes that input file is encoded using UTF-8.\n *  % iconv -f ISO-8859-1 -t UTF-8 movies-iso8859.txt > movies.txt\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code SymbolGraph} class represents an undirected graph, where the\n *  vertex names are arbitrary strings.\n *  By providing mappings between string vertex names and integers,\n *  it serves as a wrapper around the\n *  {@link Graph} data type, which assumes the vertex names are integers\n *  between 0 and <em>V</em> - 1.\n *  It also supports initializing a symbol graph from a file.\n *  <p>\n *  This implementation uses an {@link ST} to map from strings to integers,\n *  an array to map from integers to strings, and a {@link Graph} to store\n *  the underlying graph.\n *  The <em>indexOf</em> and <em>contains</em> operations take time\n *  proportional to log <em>V</em>, where <em>V</em> is the number of vertices.\n *  The <em>nameOf</em> operation takes constant time.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/41graph\">Section 4.1</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class SymbolGraph {\n    private ST<String, Integer> st;  // string -> index\n    private String[] keys;           // index  -> string\n    private Graph graph;             // the underlying graph\n\n    /**\n     * Initializes a graph from a file using the specified delimiter.\n     * Each line in the file contains\n     * the name of a vertex, followed by a list of the names\n     * of the vertices adjacent with that vertex, separated by the delimiter.\n     * @param filename the name of the file\n     * @param delimiter the delimiter between fields\n     */\n    public SymbolGraph(String filename, String delimiter) {\n        st = new ST<String, Integer>();\n\n        // First pass builds the index by reading strings to associate\n        // distinct strings with an index\n        In in = new In(filename);\n        // while (in.hasNextLine()) {\n        while (!in.isEmpty()) {\n            String[] a = in.readLine().split(delimiter);\n            for (int i = 0; i < a.length; i++) {\n                if (!st.contains(a[i]))\n                    st.put(a[i], st.size());\n            }\n        }\n\n        // inverted index to get string keys in an array\n        keys = new String[st.size()];\n        for (String name : st.keys()) {\n            keys[st.get(name)] = name;\n        }\n\n        // second pass builds the graph by connecting first vertex on each\n        // line to all others\n        graph = new Graph(st.size());\n        in = new In(filename);\n        while (in.hasNextLine()) {\n            String[] a = in.readLine().split(delimiter);\n            int v = st.get(a[0]);\n            for (int i = 1; i < a.length; i++) {\n                int w = st.get(a[i]);\n                graph.addEdge(v, w);\n            }\n        }\n    }\n\n    /**\n     * Does the graph contain the vertex named {@code s}?\n     * @param s the name of a vertex\n     * @return {@code true} if {@code s} is the name of a vertex, and {@code false} otherwise\n     */\n    public boolean contains(String s) {\n        return st.contains(s);\n    }\n\n    /**\n     * Returns the integer associated with the vertex named {@code s}.\n     * @param s the name of a vertex\n     * @return the integer (between 0 and <em>V</em> - 1) associated with the vertex named {@code s}\n     * @deprecated Replaced by {@link #indexOf(String)}.\n     */\n    @Deprecated\n    public int index(String s) {\n        return st.get(s);\n    }\n\n\n    /**\n     * Returns the integer associated with the vertex named {@code s}.\n     * @param s the name of a vertex\n     * @return the integer (between 0 and <em>V</em> - 1) associated with the vertex named {@code s}\n     */\n    public int indexOf(String s) {\n        return st.get(s);\n    }\n\n    /**\n     * Returns the name of the vertex associated with the integer {@code v}.\n     * @param  v the integer corresponding to a vertex (between 0 and <em>V</em> - 1)\n     * @return the name of the vertex associated with the integer {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @deprecated Replaced by {@link #nameOf(int)}.\n     */\n    @Deprecated\n    public String name(int v) {\n        validateVertex(v);\n        return keys[v];\n    }\n\n    /**\n     * Returns the name of the vertex associated with the integer {@code v}.\n     * @param  v the integer corresponding to a vertex (between 0 and <em>V</em> - 1)\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @return the name of the vertex associated with the integer {@code v}\n     */\n    public String nameOf(int v) {\n        validateVertex(v);\n        return keys[v];\n    }\n\n    /**\n     * Returns the graph associated with the symbol graph. It is the client's responsibility\n     * not to mutate the graph.\n     * @return the graph associated with the symbol graph\n     * @deprecated Replaced by {@link #graph()}.\n     */\n    @Deprecated\n    public Graph G() {\n        return graph;\n    }\n\n    /**\n     * Returns the graph associated with the symbol graph. It is the client's responsibility\n     * not to mutate the graph.\n     * @return the graph associated with the symbol graph\n     */\n    public Graph graph() {\n        return graph;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = graph.V();\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n\n    /**\n     * Unit tests the {@code SymbolGraph} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String filename  = args[0];\n        String delimiter = args[1];\n        SymbolGraph sg = new SymbolGraph(filename, delimiter);\n        Graph graph = sg.graph();\n        while (StdIn.hasNextLine()) {\n            String source = StdIn.readLine();\n            if (sg.contains(source)) {\n                int s = sg.index(source);\n                for (int v : graph.adj(s)) {\n                    StdOut.println(\"   \" + sg.nameOf(v));\n                }\n            }\n            else {\n                StdOut.println(\"input not contain '\" + source + \"'\");\n            }\n        }\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TST.java\n *  Execution:    java TST < words.txt\n *  Dependencies: StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/52trie/shellsST.txt\n *\n *  Symbol table with string keys, implemented using a ternary search\n *  trie (TST).\n *\n *\n *  % java TST < shellsST.txt\n *  keys(\"\"):\n *  by 4\n *  sea 6\n *  sells 1\n *  she 0\n *  shells 3\n *  shore 7\n *  the 5\n *\n *  longestPrefixOf(\"shellsort\"):\n *  shells\n *\n *  keysWithPrefix(\"shor\"):\n *  shore\n *\n *  keysThatMatch(\".he.l.\"):\n *  shells\n *\n *  % java TST\n *  theory the now is the time for all good men\n *\n *  Remarks\n *  --------\n *    - can't use a key that is the empty string \"\"\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TST} class represents a symbol table of key-value\n *  pairs, with string keys and generic values.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides character-based methods for finding the string\n *  in the symbol table that is the <em>longest prefix</em> of a given prefix,\n *  finding all strings in the symbol table that <em>start with</em> a given prefix,\n *  and finding all strings in the symbol table that <em>match</em> a given pattern.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  This implementation uses a ternary search trie.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/52trie\">Section 5.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class TST<Value> {\n    private int n;              // size\n    private Node<Value> root;   // root of TST\n\n    private static class Node<Value> {\n        private char c;                        // character\n        private Node<Value> left, mid, right;  // left, middle, and right subtries\n        private Value val;                     // value associated with string\n    }\n\n    /**\n     * Initializes an empty string symbol table.\n     */\n    public TST() {\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Does this symbol table contain the given key?\n     * @param key the key\n     * @return {@code true} if this symbol table contains {@code key} and\n     *     {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(String key) {\n        if (key == null) {\n            throw new IllegalArgumentException(\"argument to contains() is null\");\n        }\n        return get(key) != null;\n    }\n\n    /**\n     * Returns the value associated with the given key.\n     * @param key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *     and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(String key) {\n        if (key == null) {\n            throw new IllegalArgumentException(\"calls get() with null argument\");\n        }\n        if (key.length() == 0) throw new IllegalArgumentException(\"key must have length >= 1\");\n        Node<Value> x = get(root, key, 0);\n        if (x == null) return null;\n        return x.val;\n    }\n\n    // return subtrie corresponding to given key\n    private Node<Value> get(Node<Value> x, String key, int d) {\n        if (x == null) return null;\n        if (key.length() == 0) throw new IllegalArgumentException(\"key must have length >= 1\");\n        char c = key.charAt(d);\n        if      (c < x.c)              return get(x.left,  key, d);\n        else if (c > x.c)              return get(x.right, key, d);\n        else if (d < key.length() - 1) return get(x.mid,   key, d+1);\n        else                           return x;\n    }\n\n    /**\n     * Inserts the key-value pair into the symbol table, overwriting the old value\n     * with the new value if the key is already in the symbol table.\n     * If the value is {@code null}, this effectively deletes the key from the symbol table.\n     * @param key the key\n     * @param val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(String key, Value val) {\n        if (key == null) {\n            throw new IllegalArgumentException(\"calls put() with null key\");\n        }\n        if (!contains(key)) n++;\n        else if (val == null) n--;       // delete existing key\n        root = put(root, key, val, 0);\n    }\n\n    private Node<Value> put(Node<Value> x, String key, Value val, int d) {\n        char c = key.charAt(d);\n        if (x == null) {\n            x = new Node<Value>();\n            x.c = c;\n        }\n        if      (c < x.c)               x.left  = put(x.left,  key, val, d);\n        else if (c > x.c)               x.right = put(x.right, key, val, d);\n        else if (d < key.length() - 1)  x.mid   = put(x.mid,   key, val, d+1);\n        else                            x.val   = val;\n        return x;\n    }\n\n    /**\n     * Returns the string in the symbol table that is the longest prefix of {@code query},\n     * or {@code null}, if no such string.\n     * @param query the query string\n     * @return the string in the symbol table that is the longest prefix of {@code query},\n     *     or {@code null} if no such string\n     * @throws IllegalArgumentException if {@code query} is {@code null}\n     */\n    public String longestPrefixOf(String query) {\n        if (query == null) {\n            throw new IllegalArgumentException(\"calls longestPrefixOf() with null argument\");\n        }\n        if (query.length() == 0) return null;\n        int length = 0;\n        Node<Value> x = root;\n        int i = 0;\n        while (x != null && i < query.length()) {\n            char c = query.charAt(i);\n            if      (c < x.c) x = x.left;\n            else if (c > x.c) x = x.right;\n            else {\n                i++;\n                if (x.val != null) length = i;\n                x = x.mid;\n            }\n        }\n        return query.substring(0, length);\n    }\n\n    /**\n     * Returns all keys in the symbol table as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     * @return all keys in the symbol table as an {@code Iterable}\n     */\n    public Iterable<String> keys() {\n        Queue<String> queue = new Queue<String>();\n        collect(root, new StringBuilder(), queue);\n        return queue;\n    }\n\n    /**\n     * Returns all of the keys in the set that start with {@code prefix}.\n     * @param prefix the prefix\n     * @return all of the keys in the set that start with {@code prefix},\n     *     as an iterable\n     * @throws IllegalArgumentException if {@code prefix} is {@code null}\n     */\n    public Iterable<String> keysWithPrefix(String prefix) {\n        if (prefix == null) {\n            throw new IllegalArgumentException(\"calls keysWithPrefix() with null argument\");\n        }\n        Queue<String> queue = new Queue<String>();\n        Node<Value> x = get(root, prefix, 0);\n        if (x == null) return queue;\n        if (x.val != null) queue.enqueue(prefix);\n        collect(x.mid, new StringBuilder(prefix), queue);\n        return queue;\n    }\n\n    // all keys in subtrie rooted at x with given prefix\n    private void collect(Node<Value> x, StringBuilder prefix, Queue<String> queue) {\n        if (x == null) return;\n        collect(x.left,  prefix, queue);\n        if (x.val != null) queue.enqueue(prefix.toString() + x.c);\n        collect(x.mid,   prefix.append(x.c), queue);\n        prefix.deleteCharAt(prefix.length() - 1);\n        collect(x.right, prefix, queue);\n    }\n\n\n    /**\n     * Returns all of the keys in the symbol table that match {@code pattern},\n     * where the character '.' is interpreted as a wildcard character.\n     * @param pattern the pattern\n     * @return all of the keys in the symbol table that match {@code pattern},\n     *     as an iterable, where . is treated as a wildcard character.\n     */\n    public Iterable<String> keysThatMatch(String pattern) {\n        Queue<String> queue = new Queue<String>();\n        collect(root, new StringBuilder(), 0, pattern, queue);\n        return queue;\n    }\n\n    private void collect(Node<Value> x, StringBuilder prefix, int i, String pattern, Queue<String> queue) {\n        if (x == null) return;\n        char c = pattern.charAt(i);\n        if (c == '.' || c < x.c) collect(x.left, prefix, i, pattern, queue);\n        if (c == '.' || c == x.c) {\n            if (i == pattern.length() - 1 && x.val != null) queue.enqueue(prefix.toString() + x.c);\n            if (i < pattern.length() - 1) {\n                collect(x.mid, prefix.append(x.c), i+1, pattern, queue);\n                prefix.deleteCharAt(prefix.length() - 1);\n            }\n        }\n        if (c == '.' || c > x.c) collect(x.right, prefix, i, pattern, queue);\n    }\n\n\n    /**\n     * Unit tests the {@code TST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // build symbol table from standard input\n        TST<Integer> st = new TST<Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n\n        // print results\n        if (st.size() < 100) {\n            StdOut.println(\"keys(\\\"\\\"):\");\n            for (String key : st.keys()) {\n                StdOut.println(key + \" \" + st.get(key));\n            }\n            StdOut.println();\n        }\n\n        StdOut.println(\"longestPrefixOf(\\\"shellsort\\\"):\");\n        StdOut.println(st.longestPrefixOf(\"shellsort\"));\n        StdOut.println();\n\n        StdOut.println(\"longestPrefixOf(\\\"shell\\\"):\");\n        StdOut.println(st.longestPrefixOf(\"shell\"));\n        StdOut.println();\n\n        StdOut.println(\"keysWithPrefix(\\\"shor\\\"):\");\n        for (String s : st.keysWithPrefix(\"shor\"))\n            StdOut.println(s);\n        StdOut.println();\n\n        StdOut.println(\"keysThatMatch(\\\".he.l.\\\"):\");\n        for (String s : st.keysThatMatch(\".he.l.\"))\n            StdOut.println(s);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TarjanSCC.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TarjanSCC.java\n *  Execution:    Java TarjanSCC V E\n *  Dependencies: Digraph.java Stack.java TransitiveClosure.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/mediumDG.txt\n *                https://algs4.cs.princeton.edu/42digraph/largeDG.txt\n *\n *  Compute the strongly-connected components of a digraph using\n *  Tarjan's algorithm.\n *\n *  Runs in O(E + V) time.\n *\n *  % java TarjanSCC tinyDG.txt\n *  5 components\n *  1\n *  0 2 3 4 5\n *  9 10 11 12\n *  6 8\n *  7\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TarjanSCC} class represents a data type for\n *  determining the strong components in a digraph.\n *  The <em>id</em> operation determines in which strong component\n *  a given vertex lies; the <em>areStronglyConnected</em> operation\n *  determines whether two vertices are in the same strong component;\n *  and the <em>count</em> operation determines the number of strong\n *  components.\n *  <p>\n *  The <em>component identifier</em> of a vertex is an integer between\n *  0 and <em>k</em>–1, where <em>k</em> is the number of strong components.\n *  Two vertices have the same component identifier if and only if they\n *  are in the same strong component.\n *  <p>\n *  This implementation uses Tarjan's algorithm.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time,\n *  where <em>V</em> is the number of vertices and <em>E</em> is the\n *  number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  For alternative implementations of the same API, see\n *  {@link KosarajuSharirSCC} and {@link GabowSCC}.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class TarjanSCC {\n\n    private boolean[] marked;        // marked[v] = has v been visited?\n    private int[] id;                // id[v] = id of strong component containing v\n    private int[] low;               // low[v] = lowest preorder index of a vertex reachable from v\n                                     //          by following one (or more) tree edges and at most one back edge\n    private int pre;                 // preorder number counter\n    private int count;               // number of strongly-connected components\n    private Stack<Integer> stack;\n\n\n    /**\n     * Computes the strong components in a digraph.\n     * @param digraph the digraph\n     */\n    public TarjanSCC(Digraph digraph) {\n        marked = new boolean[digraph.V()];\n        stack = new Stack<Integer>();\n        id = new int[digraph.V()];\n        low = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++) {\n            if (!marked[v]) dfs(digraph, v);\n        }\n\n        // check that id[] gives strong components\n        assert check(digraph);\n    }\n\n    private void dfs(Digraph digraph, int v) {\n        marked[v] = true;\n        low[v] = pre++;\n        int min = low[v];\n        stack.push(v);\n        for (int w : digraph.adj(v)) {\n            if (!marked[w]) dfs(digraph, w);\n            if (low[w] < min) min = low[w];\n        }\n        if (min < low[v]) {\n            low[v] = min;\n            return;\n        }\n        int w;\n        do {\n            w = stack.pop();\n            id[w] = count;\n            low[w] = digraph.V();\n        } while (w != v);\n        count++;\n    }\n\n\n    /**\n     * Returns the number of strong components.\n     * @return the number of strong components\n     */\n    public int count() {\n        return count;\n    }\n\n\n    /**\n     * Are vertices {@code v} and {@code w} in the same strong component?\n     * @param  v one vertex\n     * @param  w the other vertex\n     * @return {@code true} if vertices {@code v} and {@code w} are in the same\n     *         strong component, and {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws IllegalArgumentException unless {@code 0 <= w < V}\n     */\n    public boolean stronglyConnected(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        return id[v] == id[w];\n    }\n\n    /**\n     * Returns the component id of the strong component containing vertex {@code v}.\n     * @param  v the vertex\n     * @return the component id of the strong component containing vertex {@code v}\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int id(int v) {\n        validateVertex(v);\n        return id[v];\n    }\n\n    // does the id[] array contain the strongly connected components?\n    private boolean check(Digraph digraph) {\n        TransitiveClosure tc = new TransitiveClosure(digraph);\n        for (int v = 0; v < digraph.V(); v++) {\n            for (int w = 0; w < digraph.V(); w++) {\n                if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v)))\n                    return false;\n            }\n        }\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = marked.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code TarjanSCC} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n        TarjanSCC scc = new TarjanSCC(digraph);\n\n        // number of connected components\n        int m = scc.count();\n        StdOut.println(m + \" components\");\n\n        // compute list of vertices in each strong component\n        Queue<Integer>[] components = (Queue<Integer>[]) new Queue[m];\n        for (int i = 0; i < m; i++) {\n            components[i] = new Queue<Integer>();\n        }\n        for (int v = 0; v < digraph.V(); v++) {\n            components[scc.id(v)].enqueue(v);\n        }\n\n        // print results\n        for (int i = 0; i < m; i++) {\n            for (int v : components[i]) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ThreeSum.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ThreeSum.java\n *  Execution:    java ThreeSum input.txt\n *  Dependencies: In.java StdOut.java Stopwatch.java\n *  Data files:   https://algs4.cs.princeton.edu/14analysis/1Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/2Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/4Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/8Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/16Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/32Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/1Mints.txt\n *\n *  A program with cubic running time. Reads n integers\n *  and counts the number of triples that sum to exactly 0\n *  (ignoring integer overflow).\n *\n *  % java ThreeSum 1Kints.txt\n *  70\n *\n *  % java ThreeSum 2Kints.txt\n *  528\n *\n *  % java ThreeSum 4Kints.txt\n *  4039\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code ThreeSum} class provides static methods for counting\n *  and printing the number of triples in an array of integers that sum to 0\n *  (ignoring integer overflow).\n *  <p>\n *  This implementation uses a triply nested loop and takes proportional to n^3,\n *  where n is the number of integers.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/14analysis\">Section 1.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class ThreeSum {\n\n    // Do not instantiate.\n    private ThreeSum() { }\n\n    /**\n     * Prints to standard output the (i, j, k) with {@code i < j < k}\n     * such that {@code a[i] + a[j] + a[k] == 0}.\n     *\n     * @param a the array of integers\n     */\n    public static void printAll(int[] a) {\n        int n = a.length;\n        for (int i = 0; i < n; i++) {\n            for (int j = i+1; j < n; j++) {\n                for (int k = j+1; k < n; k++) {\n                    if (a[i] + a[j] + a[k] == 0) {\n                        StdOut.println(a[i] + \" \" + a[j] + \" \" + a[k]);\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * Returns the number of triples (i, j, k) with {@code i < j < k}\n     * such that {@code a[i] + a[j] + a[k] == 0}.\n     *\n     * @param  a the array of integers\n     * @return the number of triples (i, j, k) with {@code i < j < k}\n     *         such that {@code a[i] + a[j] + a[k] == 0}\n     */\n    public static int count(int[] a) {\n        int n = a.length;\n        int count = 0;\n        for (int i = 0; i < n; i++) {\n            for (int j = i+1; j < n; j++) {\n                for (int k = j+1; k < n; k++) {\n                    if (a[i] + a[j] + a[k] == 0) {\n                        count++;\n                    }\n                }\n            }\n        }\n        return count;\n    }\n\n    /**\n     * Reads in a sequence of integers from a file, specified as a command-line argument;\n     * counts the number of triples sum to exactly zero; prints out the time to perform\n     * the computation.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args)  {\n        In in = new In(args[0]);\n        int[] a = in.readAllInts();\n\n        Stopwatch timer = new Stopwatch();\n        int count = count(a);\n        StdOut.println(\"elapsed time = \" + timer.elapsedTime());\n        StdOut.println(count);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/ThreeSumFast.java",
    "content": "/******************************************************************************\n *  Compilation:  javac ThreeSumFast.java\n *  Execution:    java ThreeSumFast input.txt\n *  Dependencies: StdOut.java In.java Stopwatch.java\n *  Data files:   https://algs4.cs.princeton.edu/14analysis/1Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/2Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/4Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/8Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/16Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/32Kints.txt\n *                https://algs4.cs.princeton.edu/14analysis/1Mints.txt\n *\n *  A program with n^2 log n running time. Reads n integers\n *  and counts the number of triples that sum to exactly 0.\n *\n *  Limitations\n *  -----------\n *     - we ignore integer overflow\n *     - doesn't handle case when input has duplicates\n *\n *\n *  % java ThreeSumFast 1Kints.txt\n *  70\n *\n *  % java ThreeSumFast 2Kints.txt\n *  528\n *\n *  % java ThreeSumFast 4Kints.txt\n *  4039\n *\n *  % java ThreeSumFast 8Kints.txt\n *  32074\n *\n *  % java ThreeSumFast 16Kints.txt\n *  255181\n *\n *  % java ThreeSumFast 32Kints.txt\n *  2052358\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\n\n/**\n *  The {@code ThreeSumFast} class provides static methods for counting\n *  and printing the number of triples in an array of distinct integers that\n *  sum to 0 (ignoring integer overflow).\n *  <p>\n *  This implementation uses sorting and binary search and takes time\n *  proportional to n^2 log n, where n is the number of integers.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/14analysis\">Section 1.4</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class ThreeSumFast {\n\n    // Do not instantiate.\n    private ThreeSumFast() { }\n\n    // returns true if the sorted array a[] contains any duplicated integers\n    private static boolean containsDuplicates(int[] a) {\n        for (int i = 1; i < a.length; i++)\n            if (a[i] == a[i-1]) return true;\n        return false;\n    }\n\n    /**\n     * Prints to standard output the (i, j, k) with {@code i < j < k}\n     * such that {@code a[i] + a[j] + a[k] == 0}.\n     *\n     * @param a the array of integers\n     * @throws IllegalArgumentException if the array contains duplicate integers\n     */\n    public static void printAll(int[] a) {\n        int n = a.length;\n        Arrays.sort(a);\n        if (containsDuplicates(a)) throw new IllegalArgumentException(\"array contains duplicate integers\");\n        for (int i = 0; i < n; i++) {\n            for (int j = i+1; j < n; j++) {\n                int k = Arrays.binarySearch(a, -(a[i] + a[j]));\n                if (k > j) StdOut.println(a[i] + \" \" + a[j] + \" \" + a[k]);\n            }\n        }\n    }\n\n    /**\n     * Returns the number of triples (i, j, k) with {@code i < j < k}\n     * such that {@code a[i] + a[j] + a[k] == 0}.\n     *\n     * @param a the array of integers\n     * @return the number of triples (i, j, k) with {@code i < j < k}\n     * such that {@code a[i] + a[j] + a[k] == 0}\n     */\n    public static int count(int[] a) {\n        int n = a.length;\n        Arrays.sort(a);\n        if (containsDuplicates(a)) throw new IllegalArgumentException(\"array contains duplicate integers\");\n        int count = 0;\n        for (int i = 0; i < n; i++) {\n            for (int j = i+1; j < n; j++) {\n                int k = Arrays.binarySearch(a, -(a[i] + a[j]));\n                if (k > j) count++;\n            }\n        }\n        return count;\n    }\n\n    /**\n     * Reads in a sequence of distinct integers from a file, specified as a command-line argument;\n     * counts the number of triples sum to exactly zero; prints out the time to perform\n     * the computation.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args)  {\n        In in = new In(args[0]);\n        int[] a = in.readAllInts();\n        int count = count(a);\n        StdOut.println(count);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TopM.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TopM.java\n *  Execution:    java TopM m < input.txt\n *  Dependencies: MinPQ.java Transaction.java StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/24pq/tinyBatch.txt\n *\n *  Given an integer m from the command line and an input stream where\n *  each line contains a String and a long value, this MinPQ client\n *  prints the m lines whose numbers are the highest.\n *\n *  % java TopM 5 < tinyBatch.txt\n *  Thompson    2/27/2000  4747.08\n *  vonNeumann  2/12/1994  4732.35\n *  vonNeumann  1/11/1999  4409.74\n *  Hoare       8/18/1992  4381.21\n *  vonNeumann  3/26/2002  4121.85\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TopM} class provides a client that reads a sequence of\n *  transactions from standard input and prints the <em>m</em> largest ones\n *  to standard output. This implementation uses a {@link MinPQ} of size\n *  at most <em>m</em> + 1 to identify the <em>M</em> largest transactions\n *  and a {@link Stack} to output them in the proper order.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/24pq\">Section 2.4</a>\n *  of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class TopM {\n\n    // This class should not be instantiated.\n    private TopM() { }\n\n    /**\n     *  Reads a sequence of transactions from standard input; takes a\n     *  command-line integer m; prints to standard output the m largest\n     *  transactions in descending order.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int m = Integer.parseInt(args[0]);\n        MinPQ<Transaction> pq = new MinPQ<Transaction>(m+1);\n\n        while (StdIn.hasNextLine()) {\n            // Create an entry from the next line and put on the PQ.\n            String line = StdIn.readLine();\n            Transaction transaction = new Transaction(line);\n            pq.insert(transaction);\n\n            // remove minimum if m+1 entries on the PQ\n            if (pq.size() > m)\n                pq.delMin();\n        }   // top m entries are on the PQ\n\n        // print entries on PQ in reverse order\n        Stack<Transaction> stack = new Stack<Transaction>();\n        for (Transaction transaction : pq)\n            stack.push(transaction);\n        for (Transaction transaction : stack)\n            StdOut.println(transaction);\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Topological.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Topological.java\n *  Execution:    java  Topological filename.txt delimiter\n *  Dependencies: Digraph.java DepthFirstOrder.java DirectedCycle.java\n *                EdgeWeightedDigraph.java EdgeWeightedDirectedCycle.java\n *                SymbolDigraph.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/jobs.txt\n *\n *  Compute topological ordering of a DAG or edge-weighted DAG.\n *  Runs in O(E + V) time.\n *\n *  % java Topological jobs.txt \"/\"\n *  Calculus\n *  Linear Algebra\n *  Introduction to CS\n *  Advanced Programming\n *  Algorithms\n *  Theoretical CS\n *  Artificial Intelligence\n *  Robotics\n *  Machine Learning\n *  Neural Networks\n *  Databases\n *  Scientific Computing\n *  Computational Biology\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Topological} class represents a data type for\n *  determining a topological order of a <em>directed acyclic graph</em> (DAG).\n *  A digraph has a topological order if and only if it is a DAG.\n *  The <em>hasOrder</em> operation determines whether the digraph has\n *  a topological order, and if so, the <em>order</em> operation\n *  returns one.\n *  <p>\n *  This implementation uses depth-first search.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the\n *  worst case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  See {@link DirectedCycle}, {@link DirectedCycleX}, and\n *  {@link EdgeWeightedDirectedCycle} for computing a directed cycle\n *  if the digraph is not a DAG.\n *  See {@link TopologicalX} for a nonrecursive, queue-based algorithm\n *  for computing a topological order of a DAG.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Topological {\n    private Iterable<Integer> order;  // topological order\n    private int[] rank;               // rank[v] = rank of vertex v in order\n\n    /**\n     * Determines whether the {@code digraph} has a topological order and, if so,\n     * finds such a topological order.\n     * @param digraph the digraph\n     */\n    public Topological(Digraph digraph) {\n        DirectedCycle finder = new DirectedCycle(digraph);\n        if (!finder.hasCycle()) {\n            DepthFirstOrder dfs = new DepthFirstOrder(digraph);\n            order = dfs.reversePost();\n            rank = new int[digraph.V()];\n            int i = 0;\n            for (int v : order)\n                rank[v] = i++;\n        }\n    }\n\n    /**\n     * Determines whether the edge-weighted digraph {@code digraph} has a topological\n     * order and, if so, finds such an order.\n     * @param digraph the edge-weighted digraph\n     */\n    public Topological(EdgeWeightedDigraph digraph) {\n        EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(digraph);\n        if (!finder.hasCycle()) {\n            DepthFirstOrder dfs = new DepthFirstOrder(digraph);\n            order = dfs.reversePost();\n        }\n    }\n\n    /**\n     * Returns a topological order if the digraph has a topological order,\n     * and {@code null} otherwise.\n     * @return a topological order of the vertices (as an iterable) if the\n     *    digraph has a topological order (or equivalently, if the digraph is a DAG),\n     *    and {@code null} otherwise\n     */\n    public Iterable<Integer> order() {\n        return order;\n    }\n\n    /**\n     * Does the digraph have a topological order?\n     * @return {@code true} if the digraph has a topological order (or equivalently,\n     *    if the digraph is a DAG), and {@code false} otherwise\n     */\n    public boolean hasOrder() {\n        return order != null;\n    }\n\n    /**\n     * Does the digraph have a topological order?\n     * @return {@code true} if the digraph has a topological order (or equivalently,\n     *    if the digraph is a DAG), and {@code false} otherwise\n     * @deprecated Replaced by {@link #hasOrder()}.\n     */\n    @Deprecated\n    public boolean isDAG() {\n        return hasOrder();\n    }\n\n    /**\n     * The rank of vertex {@code v} in the topological order;\n     * -1 if the digraph is not a DAG\n     *\n     * @param v the vertex\n     * @return the position of vertex {@code v} in a topological order\n     *    of the digraph; -1 if the digraph is not a DAG\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int rank(int v) {\n        validateVertex(v);\n        if (hasOrder()) return rank[v];\n        else            return -1;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = rank.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code Topological} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        String filename  = args[0];\n        String delimiter = args[1];\n        SymbolDigraph sg = new SymbolDigraph(filename, delimiter);\n        Topological topological = new Topological(sg.digraph());\n        for (int v : topological.order()) {\n            StdOut.println(sg.nameOf(v));\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TopologicalX.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TopologicalX.java\n *  Execution:    java TopologicalX V E F\n *  Dependencies: Queue.java Digraph.java\n *\n *  Compute topological ordering of a DAG using queue-based algorithm.\n *  Runs in O(E + V) time.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TopologicalX} class represents a data type for\n *  determining a topological order of a <em>directed acyclic graph</em> (DAG).\n *  A digraph has a topological order if and only if it is a DAG.\n *  The <em>hasOrder</em> operation determines whether the digraph has\n *  a topological order, and if so, the <em>order</em> operation\n *  returns one.\n *  <p>\n *  This implementation uses a nonrecursive, queue-based algorithm.\n *  The constructor takes &Theta;(<em>V</em> + <em>E</em>) time in the worst\n *  case, where <em>V</em> is the number of vertices and <em>E</em>\n *  is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em>) extra space (not including the digraph).\n *  <p>\n *  See {@link DirectedCycle}, {@link DirectedCycleX}, and\n *  {@link EdgeWeightedDirectedCycle} to compute a\n *  directed cycle if the digraph is not a DAG.\n *  See {@link Topological} for a recursive version that uses depth-first search.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class TopologicalX {\n    private Queue<Integer> order;     // vertices in topological order\n    private int[] ranks;              // ranks[v] = order where vertex v appears in order\n\n    /**\n     * Determines whether {@code digraph} has a topological order and, if so,\n     * finds such a topological order.\n     * @param digraph the digraph\n     */\n    public TopologicalX(Digraph digraph) {\n\n        // indegrees of remaining vertices\n        int[] indegree = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++) {\n            indegree[v] = digraph.indegree(v);\n        }\n\n        // initialize\n        ranks = new int[digraph.V()];\n        order = new Queue<Integer>();\n        int count = 0;\n\n        // initialize queue to contain all vertices with indegree = 0\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int v = 0; v < digraph.V(); v++)\n            if (indegree[v] == 0) queue.enqueue(v);\n\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            order.enqueue(v);\n            ranks[v] = count++;\n            for (int w : digraph.adj(v)) {\n                indegree[w]--;\n                if (indegree[w] == 0) queue.enqueue(w);\n            }\n        }\n\n        // there is a directed cycle in subgraph of vertices with indegree >= 1.\n        if (count != digraph.V()) {\n            order = null;\n        }\n\n        assert check(digraph);\n    }\n\n    /**\n     * Determines whether the edge-weighted {@code digraph} has a\n     * topological order and, if so, finds such a topological order.\n     * @param digraph the digraph\n     */\n    public TopologicalX(EdgeWeightedDigraph digraph) {\n\n        // indegrees of remaining vertices\n        int[] indegree = new int[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++) {\n            indegree[v] = digraph.indegree(v);\n        }\n\n        // initialize\n        ranks = new int[digraph.V()];\n        order = new Queue<Integer>();\n        int count = 0;\n\n        // initialize queue to contain all vertices with indegree = 0\n        Queue<Integer> queue = new Queue<Integer>();\n        for (int v = 0; v < digraph.V(); v++)\n            if (indegree[v] == 0) queue.enqueue(v);\n\n        while (!queue.isEmpty()) {\n            int v = queue.dequeue();\n            order.enqueue(v);\n            ranks[v] = count++;\n            for (DirectedEdge e : digraph.adj(v)) {\n                int w = e.to();\n                indegree[w]--;\n                if (indegree[w] == 0) queue.enqueue(w);\n            }\n        }\n\n        // there is a directed cycle in subgraph of vertices with indegree >= 1.\n        if (count != digraph.V()) {\n            order = null;\n        }\n\n        assert check(digraph);\n    }\n\n    /**\n     * Returns a topological order if the digraph has a topological order,\n     * and {@code null} otherwise.\n     * @return a topological order of the vertices (as an iterable) if the\n     *    digraph has a topological order (or equivalently, if the digraph is a DAG),\n     *    and {@code null} otherwise\n     */\n    public Iterable<Integer> order() {\n        return order;\n    }\n\n    /**\n     * Does the digraph have a topological order?\n     * @return {@code true} if the digraph has a topological order (or equivalently,\n     *    if the digraph is a DAG), and {@code false} otherwise\n     */\n    public boolean hasOrder() {\n        return order != null;\n    }\n\n    /**\n     * The rank of vertex {@code v} in the topological order;\n     * -1 if the digraph is not a DAG\n     *\n     * @param v vertex\n     * @return the position of vertex {@code v} in a topological order\n     *    of the digraph; -1 if the digraph is not a DAG\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     */\n    public int rank(int v) {\n        validateVertex(v);\n        if (hasOrder()) return ranks[v];\n        else            return -1;\n    }\n\n    // certify that digraph is acyclic\n    private boolean check(Digraph digraph) {\n\n        // digraph is acyclic\n        if (hasOrder()) {\n            // check that ranks are a permutation of 0 to V-1\n            boolean[] found = new boolean[digraph.V()];\n            for (int i = 0; i < digraph.V(); i++) {\n                found[rank(i)] = true;\n            }\n            for (int i = 0; i < digraph.V(); i++) {\n                if (!found[i]) {\n                    System.err.println(\"No vertex with rank \" + i);\n                    return false;\n                }\n            }\n\n            // check that ranks provide a valid topological order\n            for (int v = 0; v < digraph.V(); v++) {\n                for (int w : digraph.adj(v)) {\n                    if (rank(v) > rank(w)) {\n                        System.err.printf(\"%d-%d: rank(%d) = %d, rank(%d) = %d\\n\",\n                                          v, w, v, rank(v), w, rank(w));\n                        return false;\n                    }\n                }\n            }\n\n            // check that order() is consistent with rank()\n            int r = 0;\n            for (int v : order()) {\n                if (rank(v) != r) {\n                    System.err.println(\"order() and rank() inconsistent\");\n                    return false;\n                }\n                r++;\n            }\n        }\n\n\n        return true;\n    }\n\n    // certify that digraph is acyclic\n    private boolean check(EdgeWeightedDigraph digraph) {\n\n        // digraph is acyclic\n        if (hasOrder()) {\n            // check that ranks are a permutation of 0 to V-1\n            boolean[] found = new boolean[digraph.V()];\n            for (int i = 0; i < digraph.V(); i++) {\n                found[rank(i)] = true;\n            }\n            for (int i = 0; i < digraph.V(); i++) {\n                if (!found[i]) {\n                    System.err.println(\"No vertex with rank \" + i);\n                    return false;\n                }\n            }\n\n            // check that ranks provide a valid topological order\n            for (int v = 0; v < digraph.V(); v++) {\n                for (DirectedEdge e : digraph.adj(v)) {\n                    int w = e.to();\n                    if (rank(v) > rank(w)) {\n                        System.err.printf(\"%d-%d: rank(%d) = %d, rank(%d) = %d\\n\",\n                                          v, w, v, rank(v), w, rank(w));\n                        return false;\n                    }\n                }\n            }\n\n            // check that order() is consistent with rank()\n            int r = 0;\n            for (int v : order()) {\n                if (rank(v) != r) {\n                    System.err.println(\"order() and rank() inconsistent\");\n                    return false;\n                }\n                r++;\n            }\n        }\n\n\n        return true;\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = ranks.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code TopologicalX} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // create random DAG with V vertices and E edges; then add F random edges\n        int V = Integer.parseInt(args[0]);\n        int E = Integer.parseInt(args[1]);\n        int F = Integer.parseInt(args[2]);\n\n        Digraph digraph1 = DigraphGenerator.dag(V, E);\n\n        // corresponding edge-weighted digraph\n        EdgeWeightedDigraph digraph2 = new EdgeWeightedDigraph(V);\n        for (int v = 0; v < digraph1.V(); v++)\n            for (int w : digraph1.adj(v))\n                digraph2.addEdge(new DirectedEdge(v, w, 0.0));\n\n        // add F extra edges\n        for (int i = 0; i < F; i++) {\n            int v = StdRandom.uniformInt(V);\n            int w = StdRandom.uniformInt(V);\n            digraph1.addEdge(v, w);\n            digraph2.addEdge(new DirectedEdge(v, w, 0.0));\n        }\n\n        StdOut.println(digraph1);\n        StdOut.println();\n        StdOut.println(digraph2);\n\n        // find a directed cycle\n        TopologicalX topological1 = new TopologicalX(digraph1);\n        if (!topological1.hasOrder()) {\n            StdOut.println(\"Not a DAG\");\n        }\n\n        // or give topological sort\n        else {\n            StdOut.print(\"Topological order: \");\n            for (int v : topological1.order()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n\n        // find a directed cycle\n        TopologicalX topological2 = new TopologicalX(digraph2);\n        if (!topological2.hasOrder()) {\n            StdOut.println(\"Not a DAG\");\n        }\n\n        // or give topological sort\n        else {\n            StdOut.print(\"Topological order: \");\n            for (int v : topological2.order()) {\n                StdOut.print(v + \" \");\n            }\n            StdOut.println();\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Transaction.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Transaction.java\n *  Execution:    java Transaction\n *  Dependencies: StdOut.java\n *\n *  Data type for commercial transactions.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Arrays;\nimport java.util.Comparator;\n\n/**\n *  The {@code Transaction} class is an immutable data type to encapsulate a\n *  commercial transaction with a customer name, date, and amount.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Transaction implements Comparable<Transaction> {\n    private final String  who;      // customer\n    private final Date    when;     // date\n    private final double  amount;   // amount\n\n\n    /**\n     * Initializes a new transaction from the given arguments.\n     *\n     * @param  who the person involved in this transaction\n     * @param  when the date of this transaction\n     * @param  amount the amount of this transaction\n     * @throws IllegalArgumentException if {@code amount}\n     *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY},\n     *         or {@code Double.NEGATIVE_INFINITY}\n     */\n    public Transaction(String who, Date when, double amount) {\n        if (Double.isNaN(amount) || Double.isInfinite(amount))\n            throw new IllegalArgumentException(\"Amount cannot be NaN or infinite\");\n        this.who    = who;\n        this.when   = when;\n        this.amount = amount;\n    }\n\n    /**\n     * Initializes a new transaction by parsing a string of the form NAME DATE AMOUNT.\n     *\n     * @param  transaction the string to parse\n     * @throws IllegalArgumentException if {@code amount}\n     *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY},\n     *         or {@code Double.NEGATIVE_INFINITY}\n     */\n    public Transaction(String transaction) {\n        String[] a = transaction.split(\"\\\\s+\");\n        who    = a[0];\n        when   = new Date(a[1]);\n        amount = Double.parseDouble(a[2]);\n        if (Double.isNaN(amount) || Double.isInfinite(amount))\n            throw new IllegalArgumentException(\"Amount cannot be NaN or infinite\");\n    }\n\n    /**\n     * Returns the name of the customer involved in this transaction.\n     *\n     * @return the name of the customer involved in this transaction\n     */\n    public String who() {\n        return who;\n    }\n\n    /**\n     * Returns the date of this transaction.\n     *\n     * @return the date of this transaction\n     */\n    public Date when() {\n        return when;\n    }\n\n    /**\n     * Returns the amount of this transaction.\n     *\n     * @return the amount of this transaction\n     */\n    public double amount() {\n        return amount;\n    }\n\n    /**\n     * Returns a string representation of this transaction.\n     *\n     * @return a string representation of this transaction\n     */\n    @Override\n    public String toString() {\n        return String.format(\"%-10s %10s %8.2f\", who, when, amount);\n    }\n\n    /**\n     * Compares two transactions by amount.\n     *\n     * @param  that the other transaction\n     * @return { a negative integer, zero, a positive integer}, depending\n     *         on whether the amount of this transaction is { less than,\n     *         equal to, or greater than } the amount of that transaction\n     */\n    public int compareTo(Transaction that) {\n        return Double.compare(this.amount, that.amount);\n    }\n\n    /**\n     * Compares this transaction to the specified object.\n     *\n     * @param  other the other transaction\n     * @return true if this transaction is equal to {@code other}; false otherwise\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) return true;\n        if (other == null) return false;\n        if (other.getClass() != this.getClass()) return false;\n        Transaction that = (Transaction) other;\n        return (this.amount == that.amount) && (this.who.equals(that.who))\n                                            && (this.when.equals(that.when));\n    }\n\n\n    /**\n     * Returns a hash code for this transaction.\n     *\n     * @return a hash code for this transaction\n     */\n    public int hashCode() {\n        int hash = 1;\n        hash = 31*hash + who.hashCode();\n        hash = 31*hash + when.hashCode();\n        hash = 31*hash + ((Double) amount).hashCode();\n        return hash;\n        // return Objects.hash(who, when, amount);\n    }\n\n    /**\n     * Compares two transactions by customer name.\n     */\n    public static class WhoOrder implements Comparator<Transaction> {\n\n        @Override\n        public int compare(Transaction v, Transaction w) {\n            return v.who.compareTo(w.who);\n        }\n    }\n\n    /**\n     * Compares two transactions by date.\n     */\n    public static class WhenOrder implements Comparator<Transaction> {\n\n        @Override\n        public int compare(Transaction v, Transaction w) {\n            return v.when.compareTo(w.when);\n        }\n    }\n\n    /**\n     * Compares two transactions by amount.\n     */\n    public static class HowMuchOrder implements Comparator<Transaction> {\n\n        @Override\n        public int compare(Transaction v, Transaction w) {\n            return Double.compare(v.amount, w.amount);\n        }\n    }\n\n\n    /**\n     * Unit tests the {@code Transaction} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        Transaction[] a = new Transaction[4];\n        a[0] = new Transaction(\"Turing   6/17/1990  644.08\");\n        a[1] = new Transaction(\"Tarjan   3/26/2002 4121.85\");\n        a[2] = new Transaction(\"Knuth    6/14/1999  288.34\");\n        a[3] = new Transaction(\"Dijkstra 8/22/2007 2678.40\");\n\n        StdOut.println(\"Unsorted\");\n        for (int i = 0; i < a.length; i++)\n            StdOut.println(a[i]);\n        StdOut.println();\n\n        StdOut.println(\"Sort by date\");\n        Arrays.sort(a, new Transaction.WhenOrder());\n        for (int i = 0; i < a.length; i++)\n            StdOut.println(a[i]);\n        StdOut.println();\n\n        StdOut.println(\"Sort by customer\");\n        Arrays.sort(a, new Transaction.WhoOrder());\n        for (int i = 0; i < a.length; i++)\n            StdOut.println(a[i]);\n        StdOut.println();\n\n        StdOut.println(\"Sort by amount\");\n        Arrays.sort(a, new Transaction.HowMuchOrder());\n        for (int i = 0; i < a.length; i++)\n            StdOut.println(a[i]);\n        StdOut.println();\n    }\n\n}\n\n\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TransitiveClosure.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TransitiveClosure.java\n *  Execution:    java TransitiveClosure filename.txt\n *  Dependencies: Digraph.java DepthFirstDirectedPaths.java In.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/42digraph/tinyDG.txt\n *\n *  Compute transitive closure of a digraph and support\n *  reachability queries.\n *\n *  Preprocessing time: O(V(E + V)) time.\n *  Query time: O(1).\n *  Space: O(V^2).\n *\n *  % java TransitiveClosure tinyDG.txt\n *         0  1  2  3  4  5  6  7  8  9 10 11 12\n *  --------------------------------------------\n *    0:   T  T  T  T  T  T\n *    1:      T\n *    2:   T  T  T  T  T  T\n *    3:   T  T  T  T  T  T\n *    4:   T  T  T  T  T  T\n *    5:   T  T  T  T  T  T\n *    6:   T  T  T  T  T  T  T        T  T  T  T\n *    7:   T  T  T  T  T  T  T  T  T  T  T  T  T\n *    8:   T  T  T  T  T  T  T  T  T  T  T  T  T\n *    9:   T  T  T  T  T  T           T  T  T  T\n *   10:   T  T  T  T  T  T           T  T  T  T\n *   11:   T  T  T  T  T  T           T  T  T  T\n *   12:   T  T  T  T  T  T           T  T  T  T\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TransitiveClosure} class represents a data type for\n *  computing the transitive closure of a digraph.\n *  <p>\n *  This implementation runs depth-first search from each vertex.\n *  The constructor takes &Theta;(<em>V</em>(<em>V</em> + <em>E</em>))\n *  in the worst case, where <em>V</em> is the number of vertices and\n *  <em>E</em> is the number of edges.\n *  Each instance method takes &Theta;(1) time.\n *  It uses &Theta;(<em>V</em><sup>2</sup>) extra space (not including the digraph).\n *  <p>\n *  For large digraphs, you may want to consider a more sophisticated algorithm.\n *  <a href = \"http://www.cs.hut.fi/~enu/thesis.html\">Nuutila</a> proposes two\n *  algorithm for the problem (based on strong components and an interval representation)\n *  that runs in &Theta;(<em>E</em> + <em>V</em>) time on typical digraphs.\n *\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/42digraph\">Section 4.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class TransitiveClosure {\n    private DirectedDFS[] tc;  // tc[v] = reachable from v\n\n    /**\n     * Computes the transitive closure of a digraph.\n     * @param digraph the digraph\n     */\n    public TransitiveClosure(Digraph digraph) {\n        tc = new DirectedDFS[digraph.V()];\n        for (int v = 0; v < digraph.V(); v++)\n            tc[v] = new DirectedDFS(digraph, v);\n    }\n\n    /**\n     * Is there a directed path from vertex {@code v} to vertex {@code w} in the digraph?\n     * @param  v the source vertex\n     * @param  w the target vertex\n     * @return {@code true} if there is a directed path from {@code v} to {@code w},\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless {@code 0 <= v < V}\n     * @throws IllegalArgumentException unless {@code 0 <= w < V}\n     */\n    public boolean reachable(int v, int w) {\n        validateVertex(v);\n        validateVertex(w);\n        return tc[v].marked(w);\n    }\n\n    // throw an IllegalArgumentException unless {@code 0 <= v < V}\n    private void validateVertex(int v) {\n        int V = tc.length;\n        if (v < 0 || v >= V)\n            throw new IllegalArgumentException(\"vertex \" + v + \" is not between 0 and \" + (V-1));\n    }\n\n    /**\n     * Unit tests the {@code TransitiveClosure} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        In in = new In(args[0]);\n        Digraph digraph = new Digraph(in);\n\n        TransitiveClosure tc = new TransitiveClosure(digraph);\n\n        // print header\n        StdOut.print(\"     \");\n        for (int v = 0; v < digraph.V(); v++)\n            StdOut.printf(\"%3d\", v);\n        StdOut.println();\n        StdOut.println(\"--------------------------------------------\");\n\n        // print transitive closure\n        for (int v = 0; v < digraph.V(); v++) {\n            StdOut.printf(\"%3d: \", v);\n            for (int w = 0; w < digraph.V(); w++) {\n                if (tc.reachable(v, w)) StdOut.printf(\"  T\");\n                else                    StdOut.printf(\"   \");\n            }\n            StdOut.println();\n        }\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TrieSET.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TrieSET.java\n *  Execution:    java TrieSET < words.txt\n *  Dependencies: StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/52trie/shellsST.txt\n *\n *  A set for extended ASCII strings, implemented  using a 256-way trie.\n *\n *  Sample client reads in a list of words from standard input and\n *  prints out each word, removing any duplicates.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\nimport java.util.Iterator;\n\n/**\n *  The {@code TrieSET} class represents an ordered set of strings over\n *  the extended ASCII alphabet.\n *  It supports the usual <em>add</em>, <em>contains</em>, and <em>delete</em>\n *  methods. It also provides character-based methods for finding the string\n *  in the set that is the <em>longest prefix</em> of a given prefix,\n *  finding all strings in the set that <em>start with</em> a given prefix,\n *  and finding all strings in the set that <em>match</em> a given pattern.\n *  <p>\n *  This implementation uses a 256-way trie.\n *  The <em>add</em>, <em>contains</em>, <em>delete</em>, and\n *  <em>longest prefix</em> methods take time proportional to the length\n *  of the key (in the worst case). Construction takes constant time.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/52trie\">Section 5.2</a> of\n *  <i>Algorithms in Java, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class TrieSET implements Iterable<String> {\n    private static final int R = 256;        // extended ASCII\n\n    private Node root;      // root of trie\n    private int n;          // number of keys in trie\n\n    // R-way trie node\n    private static class Node {\n        private Node[] next = new Node[R];\n        private boolean isString;\n    }\n\n    /**\n     * Initializes an empty set of strings.\n     */\n    public TrieSET() {\n    }\n\n    /**\n     * Does the set contain the given key?\n     * @param key the key\n     * @return {@code true} if the set contains {@code key} and\n     *     {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(String key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        Node x = get(root, key, 0);\n        if (x == null) return false;\n        return x.isString;\n    }\n\n    private Node get(Node x, String key, int d) {\n        if (x == null) return null;\n        if (d == key.length()) return x;\n        char c = key.charAt(d);\n        return get(x.next[c], key, d+1);\n    }\n\n    /**\n     * Adds the key to the set if it is not already present.\n     * @param key the key to add\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void add(String key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to add() is null\");\n        root = add(root, key, 0);\n    }\n\n    private Node add(Node x, String key, int d) {\n        if (x == null) x = new Node();\n        if (d == key.length()) {\n            if (!x.isString) n++;\n            x.isString = true;\n        }\n        else {\n            char c = key.charAt(d);\n            x.next[c] = add(x.next[c], key, d+1);\n        }\n        return x;\n    }\n\n    /**\n     * Returns the number of strings in the set.\n     * @return the number of strings in the set\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Is the set empty?\n     * @return {@code true} if the set is empty, and {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns all of the keys in the set, as an iterator.\n     * To iterate over all of the keys in a set named {@code set}, use the\n     * foreach notation: {@code for (Key key : set)}.\n     * @return an iterator to all of the keys in the set\n     */\n    public Iterator<String> iterator() {\n        return keysWithPrefix(\"\").iterator();\n    }\n\n    /**\n     * Returns all of the keys in the set that start with {@code prefix}.\n     * @param prefix the prefix\n     * @return all of the keys in the set that start with {@code prefix},\n     *     as an iterable\n     */\n    public Iterable<String> keysWithPrefix(String prefix) {\n        Queue<String> results = new Queue<String>();\n        Node x = get(root, prefix, 0);\n        collect(x, new StringBuilder(prefix), results);\n        return results;\n    }\n\n    private void collect(Node x, StringBuilder prefix, Queue<String> results) {\n        if (x == null) return;\n        if (x.isString) results.enqueue(prefix.toString());\n        for (char c = 0; c < R; c++) {\n            prefix.append(c);\n            collect(x.next[c], prefix, results);\n            prefix.deleteCharAt(prefix.length() - 1);\n        }\n    }\n\n    /**\n     * Returns all of the keys in the set that match {@code pattern},\n     * where the character '.' is interpreted as a wildcard character.\n     * @param pattern the pattern\n     * @return all of the keys in the set that match {@code pattern},\n     *     as an iterable, where . is treated as a wildcard character.\n     */\n    public Iterable<String> keysThatMatch(String pattern) {\n        Queue<String> results = new Queue<String>();\n        StringBuilder prefix = new StringBuilder();\n        collect(root, prefix, pattern, results);\n        return results;\n    }\n\n    private void collect(Node x, StringBuilder prefix, String pattern, Queue<String> results) {\n        if (x == null) return;\n        int d = prefix.length();\n        if (d == pattern.length() && x.isString)\n            results.enqueue(prefix.toString());\n        if (d == pattern.length())\n            return;\n        char c = pattern.charAt(d);\n        if (c == '.') {\n            for (char ch = 0; ch < R; ch++) {\n                prefix.append(ch);\n                collect(x.next[ch], prefix, pattern, results);\n                prefix.deleteCharAt(prefix.length() - 1);\n            }\n        }\n        else {\n            prefix.append(c);\n            collect(x.next[c], prefix, pattern, results);\n            prefix.deleteCharAt(prefix.length() - 1);\n        }\n    }\n\n    /**\n     * Returns the string in the set that is the longest prefix of {@code query},\n     * or {@code null}, if no such string.\n     * @param query the query string\n     * @return the string in the set that is the longest prefix of {@code query},\n     *     or {@code null} if no such string\n     * @throws IllegalArgumentException if {@code query} is {@code null}\n     */\n    public String longestPrefixOf(String query) {\n        if (query == null) throw new IllegalArgumentException(\"argument to longestPrefixOf() is null\");\n        int length = longestPrefixOf(root, query, 0, -1);\n        if (length == -1) return null;\n        return query.substring(0, length);\n    }\n\n    // returns the length of the longest string key in the subtrie\n    // rooted at x that is a prefix of the query string,\n    // assuming the first d character match and we have already\n    // found a prefix match of the specified length\n    private int longestPrefixOf(Node x, String query, int d, int length) {\n        if (x == null) return length;\n        if (x.isString) length = d;\n        if (d == query.length()) return length;\n        char c = query.charAt(d);\n        return longestPrefixOf(x.next[c], query, d+1, length);\n    }\n\n    /**\n     * Removes the key from the set if the key is present.\n     * @param key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(String key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        root = delete(root, key, 0);\n    }\n\n    private Node delete(Node x, String key, int d) {\n        if (x == null) return null;\n        if (d == key.length()) {\n            if (x.isString) n--;\n            x.isString = false;\n        }\n        else {\n            char c = key.charAt(d);\n            x.next[c] = delete(x.next[c], key, d+1);\n        }\n\n        // remove subtrie rooted at x if it is completely empty\n        if (x.isString) return x;\n        for (int c = 0; c < R; c++)\n            if (x.next[c] != null)\n                return x;\n        return null;\n    }\n\n\n    /**\n     * Unit tests the {@code TrieSET} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        TrieSET set = new TrieSET();\n        while (!StdIn.isEmpty()) {\n            String key = StdIn.readString();\n            set.add(key);\n        }\n\n        // print results\n        if (set.size() < 100) {\n            StdOut.println(\"keys(\\\"\\\"):\");\n            for (String key : set) {\n                StdOut.println(key);\n            }\n            StdOut.println();\n        }\n\n        StdOut.println(\"longestPrefixOf(\\\"shellsort\\\"):\");\n        StdOut.println(set.longestPrefixOf(\"shellsort\"));\n        StdOut.println();\n\n        StdOut.println(\"longestPrefixOf(\\\"xshellsort\\\"):\");\n        StdOut.println(set.longestPrefixOf(\"xshellsort\"));\n        StdOut.println();\n\n        StdOut.println(\"keysWithPrefix(\\\"shor\\\"):\");\n        for (String s : set.keysWithPrefix(\"shor\"))\n            StdOut.println(s);\n        StdOut.println();\n\n        StdOut.println(\"keysWithPrefix(\\\"shortening\\\"):\");\n        for (String s : set.keysWithPrefix(\"shortening\"))\n            StdOut.println(s);\n        StdOut.println();\n\n        StdOut.println(\"keysThatMatch(\\\".he.l.\\\"):\");\n        for (String s : set.keysThatMatch(\".he.l.\"))\n            StdOut.println(s);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TrieST.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TrieST.java\n *  Execution:    java TrieST < words.txt\n *  Dependencies: StdIn.java\n *  Data files:   https://algs4.cs.princeton.edu/52trie/shellsST.txt\n *\n *  A string symbol table for extended ASCII strings, implemented\n *  using a 256-way trie.\n *\n *  % java TrieST < shellsST.txt\n *  by 4\n *  sea 6\n *  sells 1\n *  she 0\n *  shells 3\n *  shore 7\n *  the 5\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TrieST} class represents a symbol table of key-value\n *  pairs, with string keys and generic values.\n *  It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,\n *  <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.\n *  It also provides character-based methods for finding the string\n *  in the symbol table that is the <em>longest prefix</em> of a given prefix,\n *  finding all strings in the symbol table that <em>start with</em> a given prefix,\n *  and finding all strings in the symbol table that <em>match</em> a given pattern.\n *  A symbol table implements the <em>associative array</em> abstraction:\n *  when associating a value with a key that is already in the symbol table,\n *  the convention is to replace the old value with the new value.\n *  Unlike {@link java.util.Map}, this class uses the convention that\n *  values cannot be {@code null}—setting the\n *  value associated with a key to {@code null} is equivalent to deleting the key\n *  from the symbol table.\n *  <p>\n *  This implementation uses a 256-way trie.\n *  The <em>put</em>, <em>contains</em>, <em>delete</em>, and\n *  <em>longest prefix</em> operations take time proportional to the length\n *  of the key (in the worst case). Construction takes constant time.\n *  The <em>size</em>, and <em>is-empty</em> operations take constant time.\n *  Construction takes constant time.\n *  <p>\n *  For additional documentation, see <a href=\"https://algs4.cs.princeton.edu/52trie\">Section 5.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n */\npublic class TrieST<Value> {\n    private static final int R = 256;        // extended ASCII\n\n\n    private Node root;      // root of trie\n    private int n;          // number of keys in trie\n\n    // R-way trie node\n    private static class Node {\n        private Object val;\n        private Node[] next = new Node[R];\n    }\n\n   /**\n     * Initializes an empty string symbol table.\n     */\n    public TrieST() {\n    }\n\n\n    /**\n     * Returns the value associated with the given key.\n     * @param key the key\n     * @return the value associated with the given key if the key is in the symbol table\n     *     and {@code null} if the key is not in the symbol table\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public Value get(String key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to get() is null\");\n        Node x = get(root, key, 0);\n        if (x == null) return null;\n        return (Value) x.val;\n    }\n\n    /**\n     * Does this symbol table contain the given key?\n     * @param key the key\n     * @return {@code true} if this symbol table contains {@code key} and\n     *     {@code false} otherwise\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public boolean contains(String key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to contains() is null\");\n        return get(key) != null;\n    }\n\n    private Node get(Node x, String key, int d) {\n        if (x == null) return null;\n        if (d == key.length()) return x;\n        char c = key.charAt(d);\n        return get(x.next[c], key, d+1);\n    }\n\n    /**\n     * Inserts the key-value pair into the symbol table, overwriting the old value\n     * with the new value if the key is already in the symbol table.\n     * If the value is {@code null}, this effectively deletes the key from the symbol table.\n     * @param key the key\n     * @param val the value\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void put(String key, Value val) {\n        if (key == null) throw new IllegalArgumentException(\"first argument to put() is null\");\n        if (val == null) delete(key);\n        else root = put(root, key, val, 0);\n    }\n\n    private Node put(Node x, String key, Value val, int d) {\n        if (x == null) x = new Node();\n        if (d == key.length()) {\n            if (x.val == null) n++;\n            x.val = val;\n            return x;\n        }\n        char c = key.charAt(d);\n        x.next[c] = put(x.next[c], key, val, d+1);\n        return x;\n    }\n\n    /**\n     * Returns the number of key-value pairs in this symbol table.\n     * @return the number of key-value pairs in this symbol table\n     */\n    public int size() {\n        return n;\n    }\n\n    /**\n     * Is this symbol table empty?\n     * @return {@code true} if this symbol table is empty and {@code false} otherwise\n     */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /**\n     * Returns all keys in the symbol table as an {@code Iterable}.\n     * To iterate over all of the keys in the symbol table named {@code st},\n     * use the foreach notation: {@code for (Key key : st.keys())}.\n     * @return all keys in the symbol table as an {@code Iterable}\n     */\n    public Iterable<String> keys() {\n        return keysWithPrefix(\"\");\n    }\n\n    /**\n     * Returns all of the keys in the set that start with {@code prefix}.\n     * @param prefix the prefix\n     * @return all of the keys in the set that start with {@code prefix},\n     *     as an iterable\n     */\n    public Iterable<String> keysWithPrefix(String prefix) {\n        Queue<String> results = new Queue<String>();\n        Node x = get(root, prefix, 0);\n        collect(x, new StringBuilder(prefix), results);\n        return results;\n    }\n\n    private void collect(Node x, StringBuilder prefix, Queue<String> results) {\n        if (x == null) return;\n        if (x.val != null) results.enqueue(prefix.toString());\n        for (char c = 0; c < R; c++) {\n            prefix.append(c);\n            collect(x.next[c], prefix, results);\n            prefix.deleteCharAt(prefix.length() - 1);\n        }\n    }\n\n    /**\n     * Returns all of the keys in the symbol table that match {@code pattern},\n     * where the character '.' is interpreted as a wildcard character.\n     * @param pattern the pattern\n     * @return all of the keys in the symbol table that match {@code pattern},\n     *     as an iterable, where . is treated as a wildcard character.\n     */\n    public Iterable<String> keysThatMatch(String pattern) {\n        Queue<String> results = new Queue<String>();\n        collect(root, new StringBuilder(), pattern, results);\n        return results;\n    }\n\n    private void collect(Node x, StringBuilder prefix, String pattern, Queue<String> results) {\n        if (x == null) return;\n        int d = prefix.length();\n        if (d == pattern.length() && x.val != null)\n            results.enqueue(prefix.toString());\n        if (d == pattern.length())\n            return;\n        char c = pattern.charAt(d);\n        if (c == '.') {\n            for (char ch = 0; ch < R; ch++) {\n                prefix.append(ch);\n                collect(x.next[ch], prefix, pattern, results);\n                prefix.deleteCharAt(prefix.length() - 1);\n            }\n        }\n        else {\n            prefix.append(c);\n            collect(x.next[c], prefix, pattern, results);\n            prefix.deleteCharAt(prefix.length() - 1);\n        }\n    }\n\n    /**\n     * Returns the string in the symbol table that is the longest prefix of {@code query},\n     * or {@code null}, if no such string.\n     * @param query the query string\n     * @return the string in the symbol table that is the longest prefix of {@code query},\n     *     or {@code null} if no such string\n     * @throws IllegalArgumentException if {@code query} is {@code null}\n     */\n    public String longestPrefixOf(String query) {\n        if (query == null) throw new IllegalArgumentException(\"argument to longestPrefixOf() is null\");\n        int length = longestPrefixOf(root, query, 0, -1);\n        if (length == -1) return null;\n        else return query.substring(0, length);\n    }\n\n    // returns the length of the longest string key in the subtrie\n    // rooted at x that is a prefix of the query string,\n    // assuming the first d character match and we have already\n    // found a prefix match of given length (-1 if no such match)\n    private int longestPrefixOf(Node x, String query, int d, int length) {\n        if (x == null) return length;\n        if (x.val != null) length = d;\n        if (d == query.length()) return length;\n        char c = query.charAt(d);\n        return longestPrefixOf(x.next[c], query, d+1, length);\n    }\n\n    /**\n     * Removes the key from the set if the key is present.\n     * @param key the key\n     * @throws IllegalArgumentException if {@code key} is {@code null}\n     */\n    public void delete(String key) {\n        if (key == null) throw new IllegalArgumentException(\"argument to delete() is null\");\n        root = delete(root, key, 0);\n    }\n\n    private Node delete(Node x, String key, int d) {\n        if (x == null) return null;\n        if (d == key.length()) {\n            if (x.val != null) n--;\n            x.val = null;\n        }\n        else {\n            char c = key.charAt(d);\n            x.next[c] = delete(x.next[c], key, d+1);\n        }\n\n        // remove subtrie rooted at x if it is completely empty\n        if (x.val != null) return x;\n        for (int c = 0; c < R; c++)\n            if (x.next[c] != null)\n                return x;\n        return null;\n    }\n\n    /**\n     * Unit tests the {@code TrieST} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n\n        // build symbol table from standard input\n        TrieST<Integer> st = new TrieST<Integer>();\n        for (int i = 0; !StdIn.isEmpty(); i++) {\n            String key = StdIn.readString();\n            st.put(key, i);\n        }\n\n        // print results\n        if (st.size() < 100) {\n            StdOut.println(\"keys(\\\"\\\"):\");\n            for (String key : st.keys()) {\n                StdOut.println(key + \" \" + st.get(key));\n            }\n            StdOut.println();\n        }\n\n        StdOut.println(\"longestPrefixOf(\\\"shellsort\\\"):\");\n        StdOut.println(st.longestPrefixOf(\"shellsort\"));\n        StdOut.println();\n\n        StdOut.println(\"longestPrefixOf(\\\"quicksort\\\"):\");\n        StdOut.println(st.longestPrefixOf(\"quicksort\"));\n        StdOut.println();\n\n        StdOut.println(\"keysWithPrefix(\\\"shor\\\"):\");\n        for (String s : st.keysWithPrefix(\"shor\"))\n            StdOut.println(s);\n        StdOut.println();\n\n        StdOut.println(\"keysThatMatch(\\\".he.l.\\\"):\");\n        for (String s : st.keysThatMatch(\".he.l.\"))\n            StdOut.println(s);\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/TwoPersonZeroSumGame.java",
    "content": "/******************************************************************************\n *  Compilation:  javac TwoPersonZeroSumGame.java\n *  Execution:    java TwoPersonZeroSumGame m n\n *  Dependencies: LinearProgramming.java StdOut.java\n *\n *  Solve an m-by-n two-person zero-sum game by reducing it to\n *  linear programming. Assuming A is a strictly positive payoff\n *  matrix, the optimal row and column player strategies are x* and y*,\n *  scaled to be probability distributions.\n *\n *  (P)  max  y^T 1         (D)  min   1^T x\n *       s.t  A^T y <= 1         s.t   A x >= 1\n *                y >= 0                 x >= 0\n *\n *  Row player is x, column player is y.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code TwoPersonZeroSumGame} class represents a data type for\n *  computing optimal row and column strategies to two-person zero-sum games.\n *  <p>\n *  This implementation solves an <em>m</em>-by-<em>n</em> two-person\n *  zero-sum game by reducing it to a linear programming problem.\n *  Assuming the payoff matrix <em>A</em> is strictly positive, the\n *  optimal row and column player strategies x* and y* are obtained\n *  by solving the following primal and dual pair of linear programs,\n *  scaling the results to be probability distributions.\n *  <blockquote><pre>\n *  (P)  max  y^T 1           (D)  min   1^T x\n *       s.t  A^T y &le; 1         s.t   A x &ge; 1\n *                y &le; 0                 x &ge; 0\n *  </pre></blockquote>\n *  <p>\n *  If the payoff matrix <em>A</em> has any negative entries, we add\n *  the same constant to every entry so that every entry is positive.\n *  This increases the value of the game by that constant, but does not\n *  change solutions to the two-person zero-sum game.\n *  <p>\n *  This implementation is not suitable for large inputs, as it calls\n *  a bare-bones linear programming solver that is neither fast nor\n *  robust with respect to floating-point roundoff error.\n *  <p>\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/65reductions\">Section 6.5</a>\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class TwoPersonZeroSumGame {\n    private static final double EPSILON = 1.0E-8;\n\n    private final int m;            // number of rows\n    private final int n;            // number of columns\n    private LinearProgramming lp;   // linear program solver\n    private double constant;        // constant added to each entry in payoff matrix\n                                    // (0 if all entries are strictly positive)\n\n    /**\n     * Determines an optimal solution to the two-sum zero-sum game\n     * with the specified payoff matrix.\n     *\n     * @param  payoff the <em>m</em>-by-<em>n</em> payoff matrix\n     */\n    public TwoPersonZeroSumGame(double[][] payoff) {\n        m = payoff.length;\n        n = payoff[0].length;\n\n        double[] c = new double[n];\n        double[] b = new double[m];\n        double[][] A = new double[m][n];\n        for (int i = 0; i < m; i++)\n            b[i] = 1.0;\n        for (int j = 0; j < n; j++)\n            c[j] = 1.0;\n\n        // find smallest entry\n        constant = Double.POSITIVE_INFINITY;\n        for (int i = 0; i < m; i++)\n            for (int j = 0; j < n; j++)\n                if (payoff[i][j] < constant)\n                    constant = payoff[i][j];\n\n        // add constant  to every entry to make strictly positive\n        if (constant <= 0) constant = -constant + 1;\n        else               constant = 0;\n        for (int i = 0; i < m; i++)\n            for (int j = 0; j < n; j++)\n                A[i][j] = payoff[i][j] + constant;\n\n        lp = new LinearProgramming(A, b, c);\n\n        assert certifySolution(payoff);\n    }\n\n\n    /**\n     * Returns the optimal value of this two-person zero-sum game.\n     *\n     * @return the optimal value of this two-person zero-sum game\n     *\n     */\n    public double value() {\n        return 1.0 / scale() - constant;\n    }\n\n\n    // sum of x[j]\n    private double scale() {\n        double[] x = lp.primal();\n        double sum = 0.0;\n        for (int j = 0; j < n; j++)\n            sum += x[j];\n        return sum;\n    }\n\n    /**\n     * Returns the optimal row strategy of this two-person zero-sum game.\n     *\n     * @return the optimal row strategy <em>x</em> of this two-person zero-sum game\n     */\n    public double[] row() {\n        double scale = scale();\n        double[] x = lp.primal();\n        for (int j = 0; j < n; j++)\n            x[j] /= scale;\n        return x;\n    }\n\n    /**\n     * Returns the optimal column strategy of this two-person zero-sum game.\n     *\n     * @return the optimal column strategy <em>y</em> of this two-person zero-sum game\n     */\n    public double[] column() {\n        double scale = scale();\n        double[] y = lp.dual();\n        for (int i = 0; i < m; i++)\n            y[i] /= scale;\n        return y;\n    }\n\n\n    /**************************************************************************\n     *\n     *  The code below is solely for testing correctness of the data type.\n     *\n     **************************************************************************/\n\n    // is the row vector x primal feasible?\n    private boolean isPrimalFeasible() {\n        double[] x = row();\n        double sum = 0.0;\n        for (int j = 0; j < n; j++) {\n            if (x[j] < 0) {\n                StdOut.println(\"row vector not a probability distribution\");\n                StdOut.printf(\"    x[%d] = %f\\n\", j, x[j]);\n                return false;\n            }\n            sum += x[j];\n        }\n        if (Math.abs(sum - 1.0) > EPSILON) {\n            StdOut.println(\"row vector x[] is not a probability distribution\");\n            StdOut.println(\"    sum = \" + sum);\n            return false;\n        }\n        return true;\n    }\n\n    // is the column vector y dual feasible?\n    private boolean isDualFeasible() {\n        double[] y = column();\n        double sum = 0.0;\n        for (int i = 0; i < m; i++) {\n            if (y[i] < 0) {\n                StdOut.println(\"column vector y[] is not a probability distribution\");\n                StdOut.printf(\"    y[%d] = %f\\n\", i, y[i]);\n                return false;\n            }\n            sum += y[i];\n        }\n        if (Math.abs(sum - 1.0) > EPSILON) {\n            StdOut.println(\"column vector not a probability distribution\");\n            StdOut.println(\"    sum = \" + sum);\n            return false;\n        }\n        return true;\n    }\n\n    // is the solution a Nash equilibrium?\n    private boolean isNashEquilibrium(double[][] payoff) {\n        double[] x = row();\n        double[] y = column();\n        double value = value();\n\n        // given row player's mixed strategy, find column player's best pure strategy\n        double opt1 = Double.NEGATIVE_INFINITY;\n        for (int i = 0; i < m; i++) {\n            double sum = 0.0;\n            for (int j = 0; j < n; j++) {\n                sum += payoff[i][j] * x[j];\n            }\n            if (sum > opt1) opt1 = sum;\n        }\n        if (Math.abs(opt1 - value) > EPSILON) {\n            StdOut.println(\"Optimal value = \" + value);\n            StdOut.println(\"Optimal best response for column player = \" + opt1);\n            return false;\n        }\n\n        // given column player's mixed strategy, find row player's best pure strategy\n        double opt2 = Double.POSITIVE_INFINITY;\n        for (int j = 0; j < n; j++) {\n            double sum = 0.0;\n            for (int i = 0; i < m; i++) {\n                sum += payoff[i][j] * y[i];\n            }\n            if (sum < opt2) opt2 = sum;\n        }\n        if (Math.abs(opt2 - value) > EPSILON) {\n            StdOut.println(\"Optimal value = \" + value);\n            StdOut.println(\"Optimal best response for row player = \" + opt2);\n            return false;\n        }\n\n\n        return true;\n    }\n\n    private boolean certifySolution(double[][] payoff) {\n        return isPrimalFeasible() && isDualFeasible() && isNashEquilibrium(payoff);\n    }\n\n\n    private static void test(String description, double[][] payoff) {\n        StdOut.println();\n        StdOut.println(description);\n        StdOut.println(\"------------------------------------\");\n        int m = payoff.length;\n        int n = payoff[0].length;\n        TwoPersonZeroSumGame zerosum = new TwoPersonZeroSumGame(payoff);\n        double[] x = zerosum.row();\n        double[] y = zerosum.column();\n\n        StdOut.print(\"x[] = [\");\n        for (int j = 0; j < n-1; j++)\n            StdOut.printf(\"%8.4f, \", x[j]);\n        StdOut.printf(\"%8.4f]\\n\", x[n-1]);\n\n        StdOut.print(\"y[] = [\");\n        for (int i = 0; i < m-1; i++)\n            StdOut.printf(\"%8.4f, \", y[i]);\n        StdOut.printf(\"%8.4f]\\n\", y[m-1]);\n        StdOut.println(\"value =  \" + zerosum.value());\n\n    }\n\n    // row = { 4/7, 3/7 }, column = { 0, 4/7, 3/7 }, value = 20/7\n    // http://en.wikipedia.org/wiki/Zero-sum\n    private static void test1() {\n        double[][] payoff = {\n            { 30, -10,  20 },\n            { 10,  20, -20 }\n        };\n        test(\"wikipedia\", payoff);\n    }\n\n    // skew-symmetric => value = 0\n    // Linear Programming by Chvatal, p. 230\n    private static void test2() {\n        double[][] payoff = {\n            {  0,  2, -3,  0 },\n            { -2,  0,  0,  3 },\n            {  3,  0,  0, -4 },\n            {  0, -3,  4,  0 }\n        };\n        test(\"Chvatal, p. 230\", payoff);\n    }\n\n    // Linear Programming by Chvatal, p. 234\n    // row    = { 0, 56/99, 40/99, 0, 0, 2/99, 0, 1/99 }\n    // column = { 28/99, 30/99, 21/99, 20/99 }\n    // value  = 4/99\n    private static void test3() {\n        double[][] payoff = {\n            {  0,  2, -3,  0 },\n            { -2,  0,  0,  3 },\n            {  3,  0,  0, -4 },\n            {  0, -3,  4,  0 },\n            {  0,  0, -3,  3 },\n            { -2,  2,  0,  0 },\n            {  3, -3,  0,  0 },\n            {  0,  0,  4, -4 }\n        };\n        test(\"Chvatal, p. 234\", payoff);\n    }\n\n    // Linear Programming by Chvatal, p. 236\n    // row    = { 0, 2/5, 7/15, 0, 2/15, 0, 0, 0 }\n    // column = { 2/3, 0, 0, 1/3 }\n    // value  = -1/3\n    private static void test4() {\n        double[][] payoff = {\n            {  0,  2, -1, -1 },\n            {  0,  1, -2, -1 },\n            { -1, -1,  1,  1 },\n            { -1,  0,  0,  1 },\n            {  1, -2,  0, -3 },\n            {  1, -1, -1, -3 },\n            {  0, -3,  2, -1 },\n            {  0, -2,  1, -1 },\n        };\n        test(\"Chvatal p. 236\", payoff);\n    }\n\n    // rock, paper, scissors\n    // row    = { 1/3, 1/3, 1/3 }\n    // column = { 1/3, 1/3, 1/3 }\n    private static void test5() {\n        double[][] payoff = {\n            {  0, -1,  1 },\n            {  1,  0, -1 },\n            { -1,  1,  0 }\n        };\n        test(\"rock, paper, scisssors\", payoff);\n    }\n\n\n    /**\n     * Unit tests the {@code ZeroSumGameToLP} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        test1();\n        test2();\n        test3();\n        test4();\n        test5();\n\n        int m = Integer.parseInt(args[0]);\n        int n = Integer.parseInt(args[1]);\n        double[][] payoff = new double[m][n];\n        for (int i = 0; i < m; i++)\n            for (int j = 0; j < n; j++)\n                payoff[i][j] = StdRandom.uniformDouble(-0.5, 0.5);\n        test(\"random \" + m + \"-by-\" + n, payoff);\n    }\n\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/UF.java",
    "content": "/******************************************************************************\n *  Compilation:  javac UF.java\n *  Execution:    java UF < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/15uf/tinyUF.txt\n *                https://algs4.cs.princeton.edu/15uf/mediumUF.txt\n *                https://algs4.cs.princeton.edu/15uf/largeUF.txt\n *\n *  Weighted quick-union by rank with path compression by halving.\n *\n *  % java UF < tinyUF.txt\n *  4 3\n *  3 8\n *  6 5\n *  9 4\n *  2 1\n *  5 0\n *  7 2\n *  6 1\n *  2 components\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n\n/**\n *  The {@code UF} class represents a <em>union–find data type</em>\n *  (also known as the <em>disjoint-sets data type</em>).\n *  It supports the classic <em>union</em> and <em>find</em> operations,\n *  along with a <em>count</em> operation that returns the total number\n *  of sets.\n *  <p>\n *  The union–find data type models a collection of sets containing\n *  <em>n</em> elements, with each element in exactly one set.\n *  The elements are named 0 through <em>n</em>–1.\n *  Initially, there are <em>n</em> sets, with each element in its\n *  own set. The <em>canonical element</em> of a set\n *  (also known as the <em>root</em>, <em>identifier</em>,\n *  <em>leader</em>, or <em>set representative</em>)\n *  is one distinguished element in the set. Here is a summary of\n *  the operations:\n *  <ul>\n *  <li><em>find</em>(<em>p</em>) returns the canonical element\n *      of the set containing <em>p</em>. The <em>find</em> operation\n *      returns the same value for two elements if and only if\n *      they are in the same set.\n *  <li><em>union</em>(<em>p</em>, <em>q</em>) merges the set\n *      containing element <em>p</em> with the set containing\n *      element <em>q</em>. That is, if <em>p</em> and <em>q</em>\n *      are in different sets, replace these two sets\n *      with a new set that is the union of the two.\n *  <li><em>count</em>() returns the number of sets.\n *  </ul>\n *  <p>\n *  The canonical element of a set can change only when the set\n *  itself changes during a call to <em>union</em>&mdash;it cannot\n *  change during a call to either <em>find</em> or <em>count</em>.\n *  <p>\n *  This implementation uses <em>weighted quick union by rank</em>\n *  with <em>path compression by halving</em>.\n *  The constructor takes &Theta;(<em>n</em>) time, where\n *  <em>n</em> is the number of elements.\n *  The <em>union</em> and <em>find</em> operations take\n *  &Theta;(log <em>n</em>) time in the worst case.\n *  The <em>count</em> operation takes &Theta;(1) time.\n *  Moreover, starting from an empty data structure with <em>n</em> sites,\n *  any intermixed sequence of <em>m</em> <em>union</em> and <em>find</em>\n *  operations takes <em>O</em>(<em>m</em> &alpha;(<em>n</em>)) time,\n *  where &alpha;(<em>n</em>) is the inverse of\n *  <a href = \"https://en.wikipedia.org/wiki/Ackermann_function#Inverse\">Ackermann's function</a>.\n *  <p>\n *  For alternative implementations of the same API, see\n *  {@link QuickUnionUF}, {@link QuickFindUF}, and {@link WeightedQuickUnionUF}.\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/15uf\">Section 1.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\n\npublic class UF {\n\n    private int[] parent;  // parent[i] = parent of i\n    private byte[] rank;   // rank[i] = rank of subtree rooted at i (never more than 31)\n    private int count;     // number of components\n\n    /**\n     * Initializes an empty union-find data structure with\n     * {@code n} elements {@code 0} through {@code n-1}.\n     * Initially, each element is in its own set.\n     *\n     * @param  n the number of elements\n     * @throws IllegalArgumentException if {@code n < 0}\n     */\n    public UF(int n) {\n        if (n < 0) throw new IllegalArgumentException();\n        count = n;\n        parent = new int[n];\n        rank = new byte[n];\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            rank[i] = 0;\n        }\n    }\n\n    /**\n     * Returns the canonical element of the set containing element {@code p}.\n     *\n     * @param  p an element\n     * @return the canonical element of the set containing {@code p}\n     * @throws IllegalArgumentException unless {@code 0 <= p < n}\n     */\n    public int find(int p) {\n        validate(p);\n        while (p != parent[p]) {\n            parent[p] = parent[parent[p]];    // path compression by halving\n            p = parent[p];\n        }\n        return p;\n    }\n\n    /**\n     * Returns the number of sets.\n     *\n     * @return the number of sets (between {@code 1} and {@code n})\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Returns true if the two elements are in the same set.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @return {@code true} if {@code p} and {@code q} are in the same set;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     * @deprecated Replace with two calls to {@link #find(int)}.\n     */\n    @Deprecated\n    public boolean connected(int p, int q) {\n        return find(p) == find(q);\n    }\n\n    /**\n     * Merges the set containing element {@code p} with the set\n     * containing element {@code q}.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     */\n    public void union(int p, int q) {\n        int rootP = find(p);\n        int rootQ = find(q);\n        if (rootP == rootQ) return;\n\n        // make root of smaller rank point to root of larger rank\n        if      (rank[rootP] < rank[rootQ]) parent[rootP] = rootQ;\n        else if (rank[rootP] > rank[rootQ]) parent[rootQ] = rootP;\n        else {\n            parent[rootQ] = rootP;\n            rank[rootP]++;\n        }\n        count--;\n    }\n\n    // validate that p is a valid index\n    private void validate(int p) {\n        int n = parent.length;\n        if (p < 0 || p >= n) {\n            throw new IllegalArgumentException(\"index \" + p + \" is not between 0 and \" + (n-1));\n        }\n    }\n\n    /**\n     * Reads an integer {@code n} and a sequence of pairs of integers\n     * (between {@code 0} and {@code n-1}) from standard input, where each integer\n     * in the pair represents some element;\n     * if the elements are in different sets, merge the two sets\n     * and print the pair to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        UF uf = new UF(n);\n        while (!StdIn.isEmpty()) {\n            int p = StdIn.readInt();\n            int q = StdIn.readInt();\n            if (uf.find(p) == uf.find(q)) continue;\n            uf.union(p, q);\n            StdOut.println(p + \" \" + q);\n        }\n        StdOut.println(uf.count() + \" components\");\n    }\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/Vector.java",
    "content": "/******************************************************************************\n *  Compilation:  javac Vector.java\n *  Execution:    java Vector\n *  Dependencies: StdOut.java\n *\n *  Implementation of a vector of real numbers.\n *\n *  This class is implemented to be immutable: once the client program\n *  initialize a Vector, it cannot change any of its fields\n *  (d or data[i]) either directly or indirectly. Immutability is a\n *  very desirable feature of a data type.\n *\n *  % java Vector\n *     x     = [ 1.0 2.0 3.0 4.0 ]\n *     y     = [ 5.0 2.0 4.0 1.0 ]\n *     z     = [ 6.0 4.0 7.0 5.0 ]\n *   10z     = [ 60.0 40.0 70.0 50.0 ]\n *    |x|    = 5.477225575051661\n *   <x, y>  = 25.0\n *\n *\n *  Note that Vector is also the name of an unrelated Java library class\n *  in the package java.util.\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code Vector} class represents a <em>d</em>-dimensional Euclidean vector.\n *  Vectors are immutable: their values cannot be changed after they are created.\n *  It includes methods for addition, subtraction,\n *  dot product, scalar product, unit vector, Euclidean norm, and the Euclidean\n *  distance between two vectors.\n *  <p>\n *  For additional documentation,\n *  see <a href=\"https://algs4.cs.princeton.edu/12oop\">Section 1.2</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class Vector {\n\n    private int d;               // dimension of the vector\n    private double[] data;       // array of vector's components\n\n\n    /**\n     * Initializes a d-dimensional zero vector.\n     *\n     * @param d the dimension of the vector\n     */\n    public Vector(int d) {\n        this.d = d;\n        data = new double[d];\n    }\n\n    /**\n     * Initializes a vector from either an array or a vararg list.\n     * The vararg syntax supports a constructor that takes a variable number of\n     * arguments such as Vector x = new Vector(1.0, 2.0, 3.0, 4.0).\n     *\n     * @param a  the array or vararg list\n     */\n    public Vector(double... a) {\n        d = a.length;\n\n        // defensive copy so that client can't alter our copy of data[]\n        data = new double[d];\n        for (int i = 0; i < d; i++)\n            data[i] = a[i];\n    }\n\n    /**\n     * Returns the length of this vector.\n     *\n     * @return the dimension of this vector\n     * @deprecated Replaced by {@link #dimension()}.\n     */\n    @Deprecated\n    public int length() {\n        return d;\n    }\n\n    /**\n     * Returns the dimension of this vector.\n     *\n     * @return the dimension of this vector\n     */\n    public int dimension() {\n        return d;\n    }\n\n    /**\n     * Returns the dot product of this vector with the specified vector.\n     *\n     * @param  that the other vector\n     * @return the dot product of this vector and that vector\n     * @throws IllegalArgumentException if the dimensions of the two vectors are not equal\n     */\n    public double dot(Vector that) {\n        if (this.d != that.d) throw new IllegalArgumentException(\"Dimensions don't agree\");\n        double sum = 0.0;\n        for (int i = 0; i < d; i++)\n            sum = sum + (this.data[i] * that.data[i]);\n        return sum;\n    }\n\n    /**\n     * Returns the magnitude of this vector.\n     * This is also known as the L2 norm or the Euclidean norm.\n     *\n     * @return the magnitude of this vector\n     */\n    public double magnitude() {\n        return Math.sqrt(this.dot(this));\n    }\n\n    /**\n     * Returns the Euclidean distance between this vector and the specified vector.\n     *\n     * @param  that the other vector\n     * @return the Euclidean distance between this vector and that vector\n     * @throws IllegalArgumentException if the dimensions of the two vectors are not equal\n     */\n    public double distanceTo(Vector that) {\n        if (this.d != that.d) throw new IllegalArgumentException(\"Dimensions don't agree\");\n        return this.minus(that).magnitude();\n    }\n\n    /**\n     * Returns the sum of this vector and the specified vector.\n     *\n     * @param  that the vector to add to this vector\n     * @return the vector whose value is {@code (this + that)}\n     * @throws IllegalArgumentException if the dimensions of the two vectors are not equal\n     */\n    public Vector plus(Vector that) {\n        if (this.d != that.d) throw new IllegalArgumentException(\"Dimensions don't agree\");\n        Vector c = new Vector(d);\n        for (int i = 0; i < d; i++)\n            c.data[i] = this.data[i] + that.data[i];\n        return c;\n    }\n\n    /**\n     * Returns the difference between this vector and the specified vector.\n     *\n     * @param  that the vector to subtract from this vector\n     * @return the vector whose value is {@code (this - that)}\n     * @throws IllegalArgumentException if the dimensions of the two vectors are not equal\n     */\n    public Vector minus(Vector that) {\n        if (this.d != that.d) throw new IllegalArgumentException(\"Dimensions don't agree\");\n        Vector c = new Vector(d);\n        for (int i = 0; i < d; i++)\n            c.data[i] = this.data[i] - that.data[i];\n        return c;\n    }\n\n    /**\n     * Returns the ith cartesian coordinate.\n     *\n     * @param  i the coordinate index\n     * @return the ith cartesian coordinate\n     */\n    public double cartesian(int i) {\n        return data[i];\n    }\n\n    /**\n     * Returns the scalar-vector product of this vector and the specified scalar\n     *\n     * @param  alpha the scalar\n     * @return the vector whose value is {@code (alpha * this)}\n     * @deprecated Replaced by {@link #scale(double)}.\n     */\n    @Deprecated\n    public Vector times(double alpha) {\n        Vector c = new Vector(d);\n        for (int i = 0; i < d; i++)\n            c.data[i] = alpha * data[i];\n        return c;\n    }\n\n    /**\n     * Returns the scalar-vector product of this vector and the specified scalar\n     *\n     * @param  alpha the scalar\n     * @return the vector whose value is {@code (alpha * this)}\n     */\n    public Vector scale(double alpha) {\n        Vector c = new Vector(d);\n        for (int i = 0; i < d; i++)\n            c.data[i] = alpha * data[i];\n        return c;\n    }\n\n    /**\n     * Returns a unit vector in the direction of this vector.\n     *\n     * @return a unit vector in the direction of this vector\n     * @throws ArithmeticException if this vector is the zero vector\n     */\n    public Vector direction() {\n        if (this.magnitude() == 0.0) throw new ArithmeticException(\"Zero-vector has no direction\");\n        return this.times(1.0 / this.magnitude());\n    }\n\n\n    /**\n     * Returns a string representation of this vector.\n     *\n     * @return a string representation of this vector, which consists of\n     *         the vector entries, separates by single spaces\n     */\n    public String toString() {\n        StringBuilder s = new StringBuilder();\n        for (int i = 0; i < d; i++)\n            s.append(data[i] + \" \");\n        return s.toString();\n    }\n\n    /**\n     * Unit tests the {@code Vector} data type.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        double[] xdata = { 1.0, 2.0, 3.0, 4.0 };\n        double[] ydata = { 5.0, 2.0, 4.0, 1.0 };\n        Vector x = new Vector(xdata);\n        Vector y = new Vector(ydata);\n\n        StdOut.println(\"   x       = \" + x);\n        StdOut.println(\"   y       = \" + y);\n\n        Vector z = x.plus(y);\n        StdOut.println(\"   z       = \" + z);\n\n        z = z.times(10.0);\n        StdOut.println(\" 10z       = \" + z);\n\n        StdOut.println(\"  |x|      = \" + x.magnitude());\n        StdOut.println(\" <x, y>    = \" + x.dot(y));\n        StdOut.println(\"dist(x, y) = \" + x.distanceTo(y));\n        StdOut.println(\"dir(x)     = \" + x.direction());\n\n    }\n}\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  },
  {
    "path": "src/main/java/edu/princeton/cs/algs4/WeightedQuickUnionUF.java",
    "content": "/******************************************************************************\n *  Compilation:  javac WeightedQuickUnionUF.java\n *  Execution:  java WeightedQuickUnionUF < input.txt\n *  Dependencies: StdIn.java StdOut.java\n *  Data files:   https://algs4.cs.princeton.edu/15uf/tinyUF.txt\n *                https://algs4.cs.princeton.edu/15uf/mediumUF.txt\n *                https://algs4.cs.princeton.edu/15uf/largeUF.txt\n *\n *  Weighted quick-union (without path compression).\n *\n ******************************************************************************/\n\npackage edu.princeton.cs.algs4;\n\n/**\n *  The {@code WeightedQuickUnionUF} class represents a <em>union–find data type</em>\n *  (also known as the <em>disjoint-sets data type</em>).\n *  It supports the classic <em>union</em> and <em>find</em> operations,\n *  along with a <em>count</em> operation that returns the total number\n *  of sets.\n *  <p>\n *  The union–find data type models a collection of sets containing\n *  <em>n</em> elements, with each element in exactly one set.\n *  The elements are named 0 through <em>n</em>–1.\n *  Initially, there are <em>n</em> sets, with each element in its\n *  own set. The <em>canonical element</em> of a set\n *  (also known as the <em>root</em>, <em>identifier</em>,\n *  <em>leader</em>, or <em>set representative</em>)\n *  is one distinguished element in the set. Here is a summary of\n *  the operations:\n *  <ul>\n *  <li><em>find</em>(<em>p</em>) returns the canonical element\n *      of the set containing <em>p</em>. The <em>find</em> operation\n *      returns the same value for two elements if and only if\n *      they are in the same set.\n *  <li><em>union</em>(<em>p</em>, <em>q</em>) merges the set\n *      containing element <em>p</em> with the set containing\n *      element <em>q</em>. That is, if <em>p</em> and <em>q</em>\n *      are in different sets, replace these two sets\n *      with a new set that is the union of the two.\n *  <li><em>count</em>() returns the number of sets.\n *  </ul>\n *  <p>\n *  The canonical element of a set can change only when the set\n *  itself changes during a call to <em>union</em>&mdash;it cannot\n *  change during a call to either <em>find</em> or <em>count</em>.\n *  <p>\n *  This implementation uses <em>weighted quick union by size</em>\n *  (without path compression).\n *  The constructor takes &Theta;(<em>n</em>), where <em>n</em>\n *  is the number of elements.\n *  The <em>union</em> and <em>find</em>\n *  operations  take &Theta;(log <em>n</em>) time in the worst\n *  case. The <em>count</em> operation takes &Theta;(1) time.\n *  <p>\n *  For alternative implementations of the same API, see\n *  {@link UF}, {@link QuickFindUF}, and {@link QuickUnionUF}.\n *  For additional documentation, see\n *  <a href=\"https://algs4.cs.princeton.edu/15uf\">Section 1.5</a> of\n *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.\n *\n *  @author Robert Sedgewick\n *  @author Kevin Wayne\n */\npublic class WeightedQuickUnionUF {\n    private int[] parent;   // parent[i] = parent of i\n    private int[] size;     // size[i] = number of elements in subtree rooted at i\n    private int count;      // number of components\n\n    /**\n     * Initializes an empty union-find data structure with\n     * {@code n} elements {@code 0} through {@code n-1}.\n     * Initially, each element is in its own set.\n     *\n     * @param  n the number of elements\n     * @throws IllegalArgumentException if {@code n < 0}\n     */\n    public WeightedQuickUnionUF(int n) {\n        count = n;\n        parent = new int[n];\n        size = new int[n];\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            size[i] = 1;\n        }\n    }\n\n    /**\n     * Returns the number of sets.\n     *\n     * @return the number of sets (between {@code 1} and {@code n})\n     */\n    public int count() {\n        return count;\n    }\n\n    /**\n     * Returns the canonical element of the set containing element {@code p}.\n     *\n     * @param  p an element\n     * @return the canonical element of the set containing {@code p}\n     * @throws IllegalArgumentException unless {@code 0 <= p < n}\n     */\n    public int find(int p) {\n        validate(p);\n        while (p != parent[p])\n            p = parent[p];\n        return p;\n    }\n\n    /**\n     * Returns true if the two elements are in the same set.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @return {@code true} if {@code p} and {@code q} are in the same set;\n     *         {@code false} otherwise\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     * @deprecated Replace with two calls to {@link #find(int)}.\n     */\n    @Deprecated\n    public boolean connected(int p, int q) {\n        return find(p) == find(q);\n    }\n\n    // validate that p is a valid index\n    private void validate(int p) {\n        int n = parent.length;\n        if (p < 0 || p >= n) {\n            throw new IllegalArgumentException(\"index \" + p + \" is not between 0 and \" + (n-1));\n        }\n    }\n\n    /**\n     * Merges the set containing element {@code p} with the set\n     * containing element {@code q}.\n     *\n     * @param  p one element\n     * @param  q the other element\n     * @throws IllegalArgumentException unless\n     *         both {@code 0 <= p < n} and {@code 0 <= q < n}\n     */\n    public void union(int p, int q) {\n        int rootP = find(p);\n        int rootQ = find(q);\n        if (rootP == rootQ) return;\n\n        // make smaller root point to larger one\n        if (size[rootP] < size[rootQ]) {\n            parent[rootP] = rootQ;\n            size[rootQ] += size[rootP];\n        }\n        else {\n            parent[rootQ] = rootP;\n            size[rootP] += size[rootQ];\n        }\n        count--;\n    }\n\n\n    /**\n     * Reads an integer {@code n} and a sequence of pairs of integers\n     * (between {@code 0} and {@code n-1}) from standard input, where each integer\n     * in the pair represents some element;\n     * if the elements are in different sets, merge the two sets\n     * and print the pair to standard output.\n     *\n     * @param args the command-line arguments\n     */\n    public static void main(String[] args) {\n        int n = StdIn.readInt();\n        WeightedQuickUnionUF uf = new WeightedQuickUnionUF(n);\n        while (!StdIn.isEmpty()) {\n            int p = StdIn.readInt();\n            int q = StdIn.readInt();\n            if (uf.find(p) == uf.find(q)) continue;\n            uf.union(p, q);\n            StdOut.println(p + \" \" + q);\n        }\n        StdOut.println(uf.count() + \" components\");\n    }\n\n}\n\n\n/******************************************************************************\n *  Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.\n *\n *  This file is part of algs4.jar, which accompanies the textbook\n *\n *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,\n *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.\n *      http://algs4.cs.princeton.edu\n *\n *\n *  algs4.jar is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  algs4.jar is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.\n ******************************************************************************/\n"
  }
]