master
王立苏 4 years ago
commit 00a84fbc01

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../:\AI_Study\AI2021\SearchFramework1.0.1\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

@ -0,0 +1,6 @@
<component name="ArtifactManager">
<artifact type="jar" name="framework1.0.1">
<output-path>$PROJECT_DIR$/out/artifacts/framework1_0_1</output-path>
<root id="archive" name="framework1.0.1.jar" />
</artifact>
</component>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CheckStyle-IDEA">
<option name="configuration">
<map>
<entry key="checkstyle-version" value="8.40" />
<entry key="copy-libs" value="true" />
<entry key="location-0" value="BUNDLED:(bundled):Sun Checks" />
<entry key="location-1" value="BUNDLED:(bundled):Google Checks" />
<entry key="scan-before-checkin" value="false" />
<entry key="scanscope" value="JavaOnly" />
<entry key="suppress-errors" value="false" />
</map>
</option>
</component>
</project>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CsvFileAttributes">
<option name="attributeMap">
<map>
<entry key="\src\core\runner\SearchRunner.java">
<value>
<Attribute>
<option name="separator" value=";" />
</Attribute>
</value>
</entry>
<entry key="\src\core\solver\heuristic\BestFirstSearch.java">
<value>
<Attribute>
<option name="separator" value="&#9;" />
</Attribute>
</value>
</entry>
<entry key="\src\xu\problem\pathfinding\PathFinding.java">
<value>
<Attribute>
<option name="separator" value=";" />
</Attribute>
</value>
</entry>
</map>
</option>
</component>
</project>

@ -0,0 +1,464 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DataEditorManager">
<record-view-column-sorting-type value="BY_INDEX" />
<value-preview-text-wrapping value="true" />
<value-preview-pinned value="false" />
</component>
<component name="DBNavigator.Project.DataExportManager">
<export-instructions>
<create-header value="true" />
<friendly-headers value="false" />
<quote-values-containing-separator value="true" />
<quote-all-values value="false" />
<value-separator value="" />
<file-name value="" />
<file-location value="" />
<scope value="GLOBAL" />
<destination value="FILE" />
<format value="EXCEL" />
<charset value="GBK" />
</export-instructions>
</component>
<component name="DBNavigator.Project.DatabaseBrowserManager">
<autoscroll-to-editor value="false" />
<autoscroll-from-editor value="true" />
<show-object-properties value="true" />
<loaded-nodes />
</component>
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.EditorStateManager">
<last-used-providers />
</component>
<component name="DBNavigator.Project.ExecutionManager">
<retain-sticky-names value="false" />
</component>
<component name="DBNavigator.Project.MethodExecutionManager">
<method-browser />
<execution-history>
<group-entries value="true" />
<execution-inputs />
</execution-history>
<argument-values-cache />
</component>
<component name="DBNavigator.Project.ObjectDependencyManager">
<last-used-dependency-type value="INCOMING" />
</component>
<component name="DBNavigator.Project.ObjectQuickFilterManager">
<last-used-operator value="EQUAL" />
<filters />
</component>
<component name="DBNavigator.Project.ScriptExecutionManager" clear-outputs="true">
<recently-used-interfaces />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details value="false" />
</general>
<filters>
<object-type-filter>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="true" />
<object-type name="ROLE" enabled="true" />
<object-type name="PRIVILEGE" enabled="true" />
<object-type name="CHARSET" enabled="true" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED_VIEW" enabled="true" />
<object-type name="NESTED_TABLE" enabled="true" />
<object-type name="COLUMN" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET_TRIGGER" enabled="true" />
<object-type name="DATABASE_TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="true" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
<object-type name="ARGUMENT" enabled="true" />
<object-type name="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" enabled="true" />
</object-type-filter>
</filters>
<sorting>
<object-type name="COLUMN" sorting-type="NAME" />
<object-type name="FUNCTION" sorting-type="NAME" />
<object-type name="PROCEDURE" sorting-type="NAME" />
<object-type name="ARGUMENT" sorting-type="POSITION" />
</sorting>
<default-editors>
<object-type name="VIEW" editor-type="SELECTION" />
<object-type name="PACKAGE" editor-type="SELECTION" />
<object-type name="TYPE" editor-type="SELECTION" />
</default-editors>
</browser-settings>
<navigation-settings>
<lookup-filters>
<lookup-objects>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="false" />
<object-type name="ROLE" enabled="false" />
<object-type name="PRIVILEGE" enabled="false" />
<object-type name="CHARSET" enabled="false" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED VIEW" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET TRIGGER" enabled="true" />
<object-type name="DATABASE TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="false" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="true" />
</lookup-objects>
<force-database-load value="false" />
<prompt-connection-selection value="true" />
<prompt-schema-selection value="true" />
</lookup-filters>
</navigation-settings>
<dataset-grid-settings>
<general>
<enable-zooming value="true" />
<enable-column-tooltip value="true" />
</general>
<sorting>
<nulls-first value="true" />
<max-sorting-columns value="4" />
</sorting>
<tracking-columns>
<columnNames value="" />
<visible value="true" />
<editable value="false" />
</tracking-columns>
</dataset-grid-settings>
<dataset-editor-settings>
<text-editor-popup>
<active value="false" />
<active-if-empty value="false" />
<data-length-threshold value="100" />
<popup-delay value="1000" />
</text-editor-popup>
<values-actions-popup>
<show-popup-button value="true" />
<element-count-threshold value="1000" />
<data-length-threshold value="250" />
</values-actions-popup>
<general>
<fetch-block-size value="100" />
<fetch-timeout value="30" />
<trim-whitespaces value="true" />
<convert-empty-strings-to-null value="true" />
<select-content-on-cell-edit value="true" />
<large-value-preview-active value="true" />
</general>
<filters>
<prompt-filter-dialog value="true" />
<default-filter-type value="BASIC" />
</filters>
<qualified-text-editor text-length-threshold="300">
<content-types>
<content-type name="Text" enabled="true" />
<content-type name="Properties" enabled="true" />
<content-type name="XML" enabled="true" />
<content-type name="DTD" enabled="true" />
<content-type name="HTML" enabled="true" />
<content-type name="XHTML" enabled="true" />
<content-type name="CSS" enabled="true" />
<content-type name="Java" enabled="true" />
<content-type name="SQL" enabled="true" />
<content-type name="PL/SQL" enabled="true" />
<content-type name="JavaScript" enabled="true" />
<content-type name="JSON" enabled="true" />
<content-type name="JSON5" enabled="true" />
<content-type name="JSP" enabled="true" />
<content-type name="JSPx" enabled="true" />
<content-type name="Groovy" enabled="true" />
<content-type name="FTL" enabled="true" />
<content-type name="GSP" enabled="true" />
<content-type name="VTL" enabled="true" />
<content-type name="YAML" enabled="true" />
<content-type name="Manifest" enabled="true" />
</content-types>
</qualified-text-editor>
<record-navigation>
<navigation-target value="VIEWER" />
</record-navigation>
</dataset-editor-settings>
<code-editor-settings>
<general>
<show-object-navigation-gutter value="false" />
<show-spec-declaration-navigation-gutter value="true" />
<enable-spellchecking value="true" />
<enable-reference-spellchecking value="false" />
</general>
<confirmations>
<save-changes value="false" />
<revert-changes value="true" />
</confirmations>
</code-editor-settings>
<code-completion-settings>
<filters>
<basic-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="false" />
<filter-element type="OBJECT" id="view" selected="false" />
<filter-element type="OBJECT" id="materialized view" selected="false" />
<filter-element type="OBJECT" id="index" selected="false" />
<filter-element type="OBJECT" id="constraint" selected="false" />
<filter-element type="OBJECT" id="trigger" selected="false" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="false" />
<filter-element type="OBJECT" id="procedure" selected="false" />
<filter-element type="OBJECT" id="function" selected="false" />
<filter-element type="OBJECT" id="package" selected="false" />
<filter-element type="OBJECT" id="type" selected="false" />
<filter-element type="OBJECT" id="dimension" selected="false" />
<filter-element type="OBJECT" id="cluster" selected="false" />
<filter-element type="OBJECT" id="dblink" selected="false" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</basic-filter>
<extended-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</extended-filter>
</filters>
<sorting enabled="true">
<sorting-element type="RESERVED_WORD" id="keyword" />
<sorting-element type="RESERVED_WORD" id="datatype" />
<sorting-element type="OBJECT" id="column" />
<sorting-element type="OBJECT" id="table" />
<sorting-element type="OBJECT" id="view" />
<sorting-element type="OBJECT" id="materialized view" />
<sorting-element type="OBJECT" id="index" />
<sorting-element type="OBJECT" id="constraint" />
<sorting-element type="OBJECT" id="trigger" />
<sorting-element type="OBJECT" id="synonym" />
<sorting-element type="OBJECT" id="sequence" />
<sorting-element type="OBJECT" id="procedure" />
<sorting-element type="OBJECT" id="function" />
<sorting-element type="OBJECT" id="package" />
<sorting-element type="OBJECT" id="type" />
<sorting-element type="OBJECT" id="dimension" />
<sorting-element type="OBJECT" id="cluster" />
<sorting-element type="OBJECT" id="dblink" />
<sorting-element type="OBJECT" id="schema" />
<sorting-element type="OBJECT" id="role" />
<sorting-element type="OBJECT" id="user" />
<sorting-element type="RESERVED_WORD" id="function" />
<sorting-element type="RESERVED_WORD" id="parameter" />
</sorting>
<format>
<enforce-code-style-case value="true" />
</format>
</code-completion-settings>
<execution-engine-settings>
<statement-execution>
<fetch-block-size value="100" />
<execution-timeout value="20" />
<debug-execution-timeout value="600" />
<focus-result value="false" />
<prompt-execution value="false" />
</statement-execution>
<script-execution>
<command-line-interfaces />
<execution-timeout value="300" />
</script-execution>
<method-execution>
<execution-timeout value="30" />
<debug-execution-timeout value="600" />
<parameter-history-size value="10" />
</method-execution>
</execution-engine-settings>
<operation-settings>
<transactions>
<uncommitted-changes>
<on-project-close value="ASK" />
<on-disconnect value="ASK" />
<on-autocommit-toggle value="ASK" />
</uncommitted-changes>
<multiple-uncommitted-changes>
<on-commit value="ASK" />
<on-rollback value="ASK" />
</multiple-uncommitted-changes>
</transactions>
<session-browser>
<disconnect-session value="ASK" />
<kill-session value="ASK" />
<reload-on-filter-change value="false" />
</session-browser>
<compiler>
<compile-type value="KEEP" />
<compile-dependencies value="ASK" />
<always-show-controls value="false" />
</compiler>
<debugger>
<debugger-type value="ASK" />
<use-generic-runners value="true" />
</debugger>
</operation-settings>
<ddl-file-settings>
<extensions>
<mapping file-type-id="VIEW" extensions="vw" />
<mapping file-type-id="TRIGGER" extensions="trg" />
<mapping file-type-id="PROCEDURE" extensions="prc" />
<mapping file-type-id="FUNCTION" extensions="fnc" />
<mapping file-type-id="PACKAGE" extensions="pkg" />
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
<mapping file-type-id="TYPE" extensions="tpe" />
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
</extensions>
<general>
<lookup-ddl-files value="true" />
<create-ddl-files value="false" />
<synchronize-ddl-files value="true" />
<use-qualified-names value="false" />
<make-scripts-rerunnable value="true" />
</general>
</ddl-file-settings>
<general-settings>
<regional-settings>
<date-format value="MEDIUM" />
<number-format value="UNGROUPED" />
<locale value="SYSTEM_DEFAULT" />
<use-custom-formats value="false" />
</regional-settings>
<environment>
<environment-types>
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
</environment-types>
<visibility-settings>
<connection-tabs value="true" />
<dialog-headers value="true" />
<object-editor-tabs value="true" />
<script-editor-tabs value="false" />
<execution-result-tabs value="true" />
</visibility-settings>
</environment>
</general-settings>
</component>
<component name="DBNavigator.Project.StatementExecutionManager">
<execution-variables />
</component>
</project>

@ -0,0 +1,41 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="77" name="Java" />
</Languages>
</inspection_tool>
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="problem" />
</inspection_tool>
</profile>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/SearchFramework1.0.1.iml" filepath="$PROJECT_DIR$/SearchFramework1.0.1.iml" />
<module fileurl="file://$PROJECT_DIR$/../../../BackUp/Java/jdk1.8.0_131/src/jdk1.8.0_131.iml" filepath="$PROJECT_DIR$/../../../BackUp/Java/jdk1.8.0_131/src/jdk1.8.0_131.iml" />
</modules>
</component>
</project>

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="CheckStyle-IDEA-Module">
<option name="configuration">
<map />
</option>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" scope="TEST">
<library name="JUnit5.4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter/5.4.2/junit-jupiter-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.4.2/junit-jupiter-api-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.0.0/apiguardian-api-1.0.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.1.1/opentest4j-1.1.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.4.2/junit-platform-commons-1.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-params/5.4.2/junit-jupiter-params-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-engine/5.4.2/junit-jupiter-engine-5.4.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.4.2/junit-platform-engine-1.4.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/20.1.0/annotations-20.1.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: runner.SearchRunner

@ -0,0 +1,4 @@
3 5 0 8 4 2 1 7 3 6 1 2 3 4 5 6 7 8 0
3 6 4 7 8 5 0 3 2 1 1 2 3 4 5 6 7 8 0
3 8 6 7 2 5 4 3 0 1 1 2 3 4 5 6 7 8 0
4 8 13 0 6 1 15 9 14 3 4 5 11 7 2 10 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0

@ -0,0 +1,14 @@
10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 1 1 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 0 0 0
0 2 2 2 1 1 1 0 0 0
0 2 2 2 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
5 2 5 9
5 2 8 7
5 2 9 8

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: runner.SearchRunner

@ -0,0 +1,819 @@
package algs4.util;
/******************************************************************************
* Compilation: javac In.java
* Execution: java In (basic test --- see source for required files)
* Dependencies: none
*
* Reads in data of various types from standard input, files, and URLs.
*
******************************************************************************/
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.Socket;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;
/**
* <i>Input</i>. This class provides methods for reading strings
* and numbers from standard input, file input, URLs, and sockets.
* <p>
* The Locale used is: language = English, country = US. This is consistent
* with the formatting conventions with Java floating-point literals,
* command-line arguments (via {@link Double#parseDouble(String)})
* and standard output.
* <p>
* For additional documentation, see
* <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
* <i>Computer Science: An Interdisciplinary Approach</i>
* by Robert Sedgewick and Kevin Wayne.
* <p>
* Like {@link Scanner}, reading a token also consumes preceding Java
* whitespace, reading a full line consumes
* the following end-of-line delimeter, while reading a character consumes
* nothing extra.
* <p>
* Whitespace is defined in {@link Character#isWhitespace(char)}. Newlines
* consist of \n, \r, \r\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;
* see <a href="http://www.docjar.com/html/api/java/util/Scanner.java.html">
* Scanner.java</a> (NB: Java 6u23 and earlier uses only \r, \r, \r\n).
*
* @author David Pritchard
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class In {
///// begin: section (1 of 2) of code duplicated from In to StdIn.
// assume Unicode UTF-8 encoding
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with System.out.
private static final Locale LOCALE = Locale.US;
// the default token separator; we maintain the invariant that this value
// is held by the scanner's delimiter between calls
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\p{javaWhitespace}+");
// makes whitespace characters significant
private static final Pattern EMPTY_PATTERN = Pattern.compile("");
// used to read the entire input. source:
// http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html
private static final Pattern EVERYTHING_PATTERN = Pattern.compile("\\A");
//// end: section (1 of 2) of code duplicated from In to StdIn.
private Scanner scanner;
/**
* Initializes an input stream from standard input.
*/
public In() {
scanner = new Scanner(new BufferedInputStream(System.in), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
/**
* Initializes an input stream from a socket.
*
* @param socket the socket
* @throws IllegalArgumentException if cannot open {@code socket}
* @throws IllegalArgumentException if {@code socket} is {@code null}
*/
public In(Socket socket) {
if (socket == null) throw new IllegalArgumentException("socket argument is null");
try {
InputStream is = socket.getInputStream();
scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + socket, ioe);
}
}
/**
* Initializes an input stream from a URL.
*
* @param url the URL
* @throws IllegalArgumentException if cannot open {@code url}
* @throws IllegalArgumentException if {@code url} is {@code null}
*/
public In(URL url) {
if (url == null) throw new IllegalArgumentException("url argument is null");
try {
URLConnection site = url.openConnection();
InputStream is = site.getInputStream();
scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + url, ioe);
}
}
/**
* Initializes an input stream from a file.
*
* @param file the file
* @throws IllegalArgumentException if cannot open {@code file}
* @throws IllegalArgumentException if {@code file} is {@code null}
*/
public In(File file) {
if (file == null) throw new IllegalArgumentException("file argument is null");
try {
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream fis = new FileInputStream(file);
scanner = new Scanner(new BufferedInputStream(fis), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + file, ioe);
}
}
/**
* Initializes an input stream from a filename or web page name.
*
* @param name the filename or web page name
* @throws IllegalArgumentException if cannot open {@code name} as
* a file or URL
* @throws IllegalArgumentException if {@code name} is {@code null}
*/
public In(String name) {
if (name == null) throw new IllegalArgumentException("argument is null");
if (name.length() == 0) throw new IllegalArgumentException("argument is the empty string");
try {
// first try to read file from local file system
File file = new File(name);
if (file.exists()) {
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream fis = new FileInputStream(file);
scanner = new Scanner(new BufferedInputStream(fis), CHARSET_NAME);
scanner.useLocale(LOCALE);
return;
}
// resource relative to .class file
URL url = getClass().getResource(name);
// resource relative to classloader root
if (url == null) {
url = getClass().getClassLoader().getResource(name);
}
// or URL from web
if (url == null) {
url = new URL(name);
}
URLConnection site = url.openConnection();
// in order to set User-Agent, replace above line with these two
// HttpURLConnection site = (HttpURLConnection) url.openConnection();
// site.addRequestProperty("User-Agent", "Mozilla/4.76");
InputStream is = site.getInputStream();
scanner = new Scanner(new BufferedInputStream(is), CHARSET_NAME);
scanner.useLocale(LOCALE);
}
catch (IOException ioe) {
throw new IllegalArgumentException("Could not open " + name, ioe);
}
}
/**
* Initializes an input stream from a given {@link Scanner} source; use with
* {@code new Scanner(String)} to read from a string.
* <p>
* Note that this does not create a defensive copy, so the
* scanner will be mutated as you read on.
*
* @param scanner the scanner
* @throws IllegalArgumentException if {@code scanner} is {@code null}
*/
public In(Scanner scanner) {
if (scanner == null) throw new IllegalArgumentException("scanner argument is null");
this.scanner = scanner;
}
/**
* Returns true if this input stream exists.
*
* @return {@code true} if this input stream exists; {@code false} otherwise
*/
public boolean exists() {
return scanner != null;
}
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from "public" to "public static".
/**
* Returns true if input stream is empty (except possibly whitespace).
* Use this to know whether the next call to {@link #readString()},
* {@link #readDouble()}, etc will succeed.
*
* @return {@code true} if this input stream is empty (except possibly whitespace);
* {@code false} otherwise
*/
public boolean isEmpty() {
return !scanner.hasNext();
}
/**
* Returns true if this input stream has a next line.
* Use this method to know whether the
* next call to {@link #readLine()} will succeed.
* This method is functionally equivalent to {@link #hasNextChar()}.
*
* @return {@code true} if this input stream has more input (including whitespace);
* {@code false} otherwise
*/
public boolean hasNextLine() {
return scanner.hasNextLine();
}
/**
* Returns true if this input stream has more input (including whitespace).
* Use this method to know whether the next call to {@link #readChar()} will succeed.
* This method is functionally equivalent to {@link #hasNextLine()}.
*
* @return {@code true} if this input stream has more input (including whitespace);
* {@code false} otherwise
*/
public boolean hasNextChar() {
scanner.useDelimiter(EMPTY_PATTERN);
boolean result = scanner.hasNext();
scanner.useDelimiter(WHITESPACE_PATTERN);
return result;
}
/**
* Reads and returns the next line in this input stream.
*
* @return the next line in this input stream; {@code null} if no such line
*/
public String readLine() {
String line;
try {
line = scanner.nextLine();
}
catch (NoSuchElementException e) {
line = null;
}
return line;
}
/**
* Reads and returns the next character in this input stream.
*
* @return the next {@code char} in this input stream
* @throws NoSuchElementException if the input stream is empty
*/
public char readChar() {
scanner.useDelimiter(EMPTY_PATTERN);
try {
String ch = scanner.next();
assert ch.length() == 1 : "Internal (Std)In.readChar() error!"
+ " Please contact the authors.";
scanner.useDelimiter(WHITESPACE_PATTERN);
return ch.charAt(0);
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'char' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads and returns the remainder of this input stream, as a string.
*
* @return the remainder of this input stream, as a string
*/
public String readAll() {
if (!scanner.hasNextLine())
return "";
String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();
// not that important to reset delimeter, since now scanner is empty
scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway
return result;
}
/**
* Reads the next token from this input stream and returns it as a {@code String}.
*
* @return the next {@code String} in this input stream
* @throws NoSuchElementException if the input stream is empty
*/
public String readString() {
try {
return scanner.next();
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'String' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code int},
* and returns the {@code int}.
*
* @return the next {@code int} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as an {@code int}
*/
public int readInt() {
try {
return scanner.nextInt();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read an 'int' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read an 'int' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code double},
* and returns the {@code double}.
*
* @return the next {@code double} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code double}
*/
public double readDouble() {
try {
return scanner.nextDouble();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'double' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'double' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code float},
* and returns the {@code float}.
*
* @return the next {@code float} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code float}
*/
public float readFloat() {
try {
return scanner.nextFloat();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'float' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'float' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code long},
* and returns the {@code long}.
*
* @return the next {@code long} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code long}
*/
public long readLong() {
try {
return scanner.nextLong();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'long' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'long' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code short},
* and returns the {@code short}.
*
* @return the next {@code short} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code short}
*/
public short readShort() {
try {
return scanner.nextShort();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'short' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'short' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code byte},
* and returns the {@code byte}.
* <p>
* To read binary data, use {@link BinaryIn}.
*
* @return the next {@code byte} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code byte}
*/
public byte readByte() {
try {
return scanner.nextByte();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'byte' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read a 'byte' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from this input stream, parses it as a {@code boolean}
* (interpreting either {@code "true"} or {@code "1"} as {@code true},
* and either {@code "false"} or {@code "0"} as {@code false}).
*
* @return the next {@code boolean} in this input stream
* @throws NoSuchElementException if the input stream is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code boolean}
*/
public boolean readBoolean() {
try {
String token = readString();
if ("true".equalsIgnoreCase(token)) return true;
if ("false".equalsIgnoreCase(token)) return false;
if ("1".equals(token)) return true;
if ("0".equals(token)) return false;
throw new InputMismatchException("attempts to read a 'boolean' value from the input stream, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'boolean' value from the input stream, "
+ "but no more tokens are available");
}
}
/**
* Reads all remaining tokens from this input stream and returns them as
* an array of strings.
*
* @return all remaining tokens in this input stream, as an array of strings
*/
public String[] readAllStrings() {
// we could use readAll.trim().split(), but that's not consistent
// since trim() uses characters 0x00..0x20 as whitespace
String[] tokens = WHITESPACE_PATTERN.split(readAll());
if (tokens.length == 0 || tokens[0].length() > 0)
return tokens;
String[] decapitokens = new String[tokens.length-1];
for (int i = 0; i < tokens.length-1; i++)
decapitokens[i] = tokens[i+1];
return decapitokens;
}
/**
* Reads all remaining lines from this input stream and returns them as
* an array of strings.
*
* @return all remaining lines in this input stream, as an array of strings
*/
public String[] readAllLines() {
ArrayList<String> lines = new ArrayList<String>();
while (hasNextLine()) {
lines.add(readLine());
}
return lines.toArray(new String[lines.size()]);
}
/**
* Reads all remaining tokens from this input stream, parses them as integers,
* and returns them as an array of integers.
*
* @return all remaining lines in this input stream, as an array of integers
*/
public int[] readAllInts() {
String[] fields = readAllStrings();
int[] vals = new int[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Integer.parseInt(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from this input stream, parses them as longs,
* and returns them as an array of longs.
*
* @return all remaining lines in this input stream, as an array of longs
*/
public long[] readAllLongs() {
String[] fields = readAllStrings();
long[] vals = new long[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Long.parseLong(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from this input stream, parses them as doubles,
* and returns them as an array of doubles.
*
* @return all remaining lines in this input stream, as an array of doubles
*/
public double[] readAllDoubles() {
String[] fields = readAllStrings();
double[] vals = new double[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Double.parseDouble(fields[i]);
return vals;
}
///// end: section (2 of 2) of code duplicated from In to StdIn */
/**
* Closes this input stream.
*/
public void close() {
scanner.close();
}
/**
* Reads all integers from a file and returns them as
* an array of integers.
*
* @param filename the name of the file
* @return the integers in the file
* @deprecated Replaced by {@code new In(filename)}.{@link #readAllInts()}.
*/
@Deprecated
public static int[] readInts(String filename) {
return new In(filename).readAllInts();
}
/**
* Reads all doubles from a file and returns them as
* an array of doubles.
*
* @param filename the name of the file
* @return the doubles in the file
* @deprecated Replaced by {@code new In(filename)}.{@link #readAllDoubles()}.
*/
@Deprecated
public static double[] readDoubles(String filename) {
return new In(filename).readAllDoubles();
}
/**
* Reads all strings from a file and returns them as
* an array of strings.
*
* @param filename the name of the file
* @return the strings in the file
* @deprecated Replaced by {@code new In(filename)}.{@link #readAllStrings()}.
*/
@Deprecated
public static String[] readStrings(String filename) {
return new In(filename).readAllStrings();
}
/**
* Reads all integers from standard input and returns them
* an array of integers.
*
* @return the integers on standard input
* @deprecated Replaced by {@link StdIn#readAllInts()}.
*/
@Deprecated
public static int[] readInts() {
return new In().readAllInts();
}
/**
* Reads all doubles from standard input and returns them as
* an array of doubles.
*
* @return the doubles on standard input
* @deprecated Replaced by {@link StdIn#readAllDoubles()}.
*/
@Deprecated
public static double[] readDoubles() {
return new In().readAllDoubles();
}
/**
* Reads all strings from standard input and returns them as
* an array of strings.
*
* @return the strings on standard input
* @deprecated Replaced by {@link StdIn#readAllStrings()}.
*/
@Deprecated
public static String[] readStrings() {
return new In().readAllStrings();
}
/**
* Unit tests the {@code In} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in;
String urlName = "https://introcs.cs.princeton.edu/java/stdlib/InTest.txt";
// read from a URL
System.out.println("readAll() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
System.out.println(in.readAll());
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from URL
System.out.println("readLine() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one string at a time from URL
System.out.println("readString() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
while (!in.isEmpty()) {
String s = in.readString();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from file in current directory
System.out.println("readLine() from current directory");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("./InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from file using relative path
System.out.println("readLine() from relative path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("../stdlib/InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one char at a time
System.out.println("readChar() from file");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("InTest.txt");
while (!in.isEmpty()) {
char c = in.readChar();
System.out.print(c);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
System.out.println();
// read one line at a time from absolute OS X / Linux path
System.out.println("readLine() from absolute OS X / Linux path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("/n/fs/introcs/www/java/stdlib/InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from absolute Windows path
System.out.println("readLine() from absolute Windows path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("G:\\www\\introcs\\stdlib\\InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
System.out.println();
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,341 @@
package algs4.util;
/******************************************************************************
* Compilation: javac Out.java
* Execution: java Out
* Dependencies: none
*
* Writes data of various types to: stdout, file, or socket.
*
******************************************************************************/
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Locale;
/**
* This class provides methods for writing strings and numbers to
* various output streams, including standard output, file, and sockets.
* <p>
* For additional documentation, see
* <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
* <i>Computer Science: An Interdisciplinary Approach</i>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Out {
// force Unicode UTF-8 encoding; otherwise it's system dependent
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with In
private static final Locale LOCALE = Locale.US;
private PrintWriter out;
/**
* Initializes an output stream from a {@link OutputStream}.
*
* @param os the {@code OutputStream}
*/
public Out(OutputStream os) {
try {
OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET_NAME);
out = new PrintWriter(osw, true);
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Initializes an output stream from standard output.
*/
public Out() {
this(System.out);
}
/**
* Initializes an output stream from a socket.
*
* @param socket the socket
*/
public Out(Socket socket) {
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET_NAME);
out = new PrintWriter(osw, true);
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Initializes an output stream from a file.
*
* @param filename the name of the file
*/
public Out(String filename) {
try {
OutputStream os = new FileOutputStream(filename);
OutputStreamWriter osw = new OutputStreamWriter(os, CHARSET_NAME);
out = new PrintWriter(osw, true);
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Closes the output stream.
*/
public void close() {
out.close();
}
/**
* Terminates the current line by printing the line-separator string.
*/
public void println() {
out.println();
}
/**
* Prints an object to this output stream and then terminates the line.
*
* @param x the object to print
*/
public void println(Object x) {
out.println(x);
}
/**
* Prints a boolean to this output stream and then terminates the line.
*
* @param x the boolean to print
*/
public void println(boolean x) {
out.println(x);
}
/**
* Prints a character to this output stream and then terminates the line.
*
* @param x the character to print
*/
public void println(char x) {
out.println(x);
}
/**
* Prints a double to this output stream and then terminates the line.
*
* @param x the double to print
*/
public void println(double x) {
out.println(x);
}
/**
* Prints a float to this output stream and then terminates the line.
*
* @param x the float to print
*/
public void println(float x) {
out.println(x);
}
/**
* Prints an integer to this output stream and then terminates the line.
*
* @param x the integer to print
*/
public void println(int x) {
out.println(x);
}
/**
* Prints a long to this output stream and then terminates the line.
*
* @param x the long to print
*/
public void println(long x) {
out.println(x);
}
/**
* Prints a byte to this output stream and then terminates the line.
* <p>
* To write binary data, see {@link BinaryOut}.
*
* @param x the byte to print
*/
public void println(byte x) {
out.println(x);
}
/**
* Flushes this output stream.
*/
public void print() {
out.flush();
}
/**
* Prints an object to this output stream and flushes this output stream.
*
* @param x the object to print
*/
public void print(Object x) {
out.print(x);
out.flush();
}
/**
* Prints a boolean to this output stream and flushes this output stream.
*
* @param x the boolean to print
*/
public void print(boolean x) {
out.print(x);
out.flush();
}
/**
* Prints a character to this output stream and flushes this output stream.
*
* @param x the character to print
*/
public void print(char x) {
out.print(x);
out.flush();
}
/**
* Prints a double to this output stream and flushes this output stream.
*
* @param x the double to print
*/
public void print(double x) {
out.print(x);
out.flush();
}
/**
* Prints a float to this output stream and flushes this output stream.
*
* @param x the float to print
*/
public void print(float x) {
out.print(x);
out.flush();
}
/**
* Prints an integer to this output stream and flushes this output stream.
*
* @param x the integer to print
*/
public void print(int x) {
out.print(x);
out.flush();
}
/**
* Prints a long integer to this output stream and flushes this output stream.
*
* @param x the long integer to print
*/
public void print(long x) {
out.print(x);
out.flush();
}
/**
* Prints a byte to this output stream and flushes this output stream.
*
* @param x the byte to print
*/
public void print(byte x) {
out.print(x);
out.flush();
}
/**
* Prints a formatted string to this output stream, using the specified format
* string and arguments, and then flushes this output stream.
*
* @param format the format string
* @param args the arguments accompanying the format string
*/
public void printf(String format, Object... args) {
out.printf(LOCALE, format, args);
out.flush();
}
/**
* Prints a formatted string to this output stream, using the specified
* locale, format string, and arguments, and then flushes this output stream.
*
* @param locale the locale
* @param format the format string
* @param args the arguments accompanying the format string
*/
public void printf(Locale locale, String format, Object... args) {
out.printf(locale, format, args);
out.flush();
}
/**
* A test client.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
Out out;
// write to stdout
out = new Out();
out.println("Test 1");
out.close();
// write to a file
out = new Out("test.txt");
out.println("Test 2");
out.close();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,696 @@
/******************************************************************************
* Compilation: javac StdIn.java
* Execution: java StdIn (interactive test of basic functionality)
* Dependencies: none
*
* Reads in data of various types from standard input.
*
******************************************************************************/
package algs4.util;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;
/**
* The {@code StdIn} class provides static methods for reading strings
* and numbers from standard input.
* These functions fall into one of four categories:
* <ul>
* <li>those for reading individual tokens from standard input, one at a time,
* and converting each to a number, string, or boolean
* <li>those for reading characters from standard input, one at a time
* <li>those for reading lines from standard input, one at a time
* <li>those for reading a sequence of values of the same type from standard input,
* and returning the values in an array
* </ul>
* <p>
* Generally, it is best not to mix functions from the different
* categories in the same program.
* <p>
* <b>Getting started.</b>
* To use this class, you must have {@code StdIn.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
* and add to your Java classpath or download
* <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdIn.java">StdIn.java</a>
* and put a copy in your working directory.
* <p>
* <b>Reading tokens from standard input and converting to numbers and strings.</b>
* You can use the following methods to read numbers, strings, and booleans
* from standard input one at a time:
* <ul>
* <li> {@link #isEmpty()}
* <li> {@link #readInt()}
* <li> {@link #readDouble()}
* <li> {@link #readString()}
* <li> {@link #readShort()}
* <li> {@link #readLong()}
* <li> {@link #readFloat()}
* <li> {@link #readByte()}
* <li> {@link #readBoolean()}
* </ul>
* <p>
* The first method returns true if standard input has no more tokens.
* Each other method skips over any input that is whitespace. Then, it reads
* the next token and attempts to convert it into a value of the specified
* type. If it succeeds, it returns that value; otherwise, it
* throws an {@link InputMismatchException}.
* <p>
* <em>Whitespace</em> includes spaces, tabs, and newlines; the full definition
* is inherited from {@link Character#isWhitespace(char)}.
* A <em>token</em> is a maximal sequence of non-whitespace characters.
* The precise rules for describing which tokens can be converted to
* integers and floating-point numbers are inherited from
* <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#number-syntax">Scanner</a>,
* using the locale {@link Locale#US}; the rules
* for floating-point numbers are slightly different
* from those in {@link Double#valueOf(String)},
* but unlikely to be of concern to most programmers.
* <p>
* As an example, the following code fragment reads integers from standard input,
* one at a time, and prints them one per line.
* <pre>
* while (!StdIn.isEmpty()) {
* double value = StdIn.readDouble();
* StdOut.println(value);
* }
* </pre>
* <p>
* <b>Reading characters from standard input.</b>
* You can use the following two methods to read characters from standard input one at a time:
* <ul>
* <li> {@link #hasNextChar()}
* <li> {@link #readChar()}
* </ul>
* <p>
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the next character of input on standard
* input (possibly a whitespace character).
* <p>
* As an example, the following code fragment reads characters from standard input,
* one character at a time, and prints it to standard output.
* <pre>
* while (StdIn.hasNextChar()) {
* char c = StdIn.readChar();
* StdOut.print(c);
* }
* </pre>
* <p>
* <b>Reading lines from standard input.</b>
* You can use the following two methods to read lines from standard input:
* <ul>
* <li> {@link #hasNextLine()}
* <li> {@link #readLine()}
* </ul>
* <p>
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the remaining portion of
* the next line of input on standard input (possibly whitespace),
* discarding the trailing line separator.
* <p>
* A <em>line separator</em> is defined to be one of the following strings:
* {@code \n} (Linux), {@code \r} (old Macintosh),
* {@code \r\n} (Windows),
* {@code \}{@code u2028}, {@code \}{@code u2029}, or {@code \}{@code u0085}.
* <p>
* As an example, the following code fragment reads text from standard input,
* one line at a time, and prints it to standard output.
* <pre>
* while (StdIn.hasNextLine()) {
* String line = StdIn.readLine();
* StdOut.println(line);
* }
* </pre>
* <p>
* <b>Reading a sequence of values of the same type from standard input.</b>
* You can use the following methods to read a sequence numbers, strings,
* or booleans (all of the same type) from standard input:
* <ul>
* <li> {@link #readAllDoubles()}
* <li> {@link #readAllInts()}
* <li> {@link #readAllLongs()}
* <li> {@link #readAllStrings()}
* <li> {@link #readAllLines()}
* <li> {@link #readAll()}
* </ul>
* <p>
* The first three methods read of all of remaining token on standard input
* and converts the tokens to values of
* the specified type, as in the corresponding
* {@code readDouble}, {@code readInt}, and {@code readString()} methods.
* The {@code readAllLines()} method reads all remaining lines on standard
* input and returns them as an array of strings.
* The {@code readAll()} method reads all remaining input on standard
* input and returns it as a string.
* <p>
* As an example, the following code fragment reads all of the remaining
* tokens from standard input and returns them as an array of strings.
* <pre>
* String[] words = StdIn.readAllStrings();
* </pre>
* <p>
* <b>Differences with Scanner.</b>
* {@code StdIn} and {@link Scanner} are both designed to parse
* tokens and convert them to primitive types and strings.
* The main differences are summarized below:
* <ul>
* <li> {@code StdIn} is a set of static methods and reads
* reads input from only standard input. It is suitable for use before
* a programmer knows about objects.
* See {@link In} for an object-oriented version that handles
* input from files, URLs,
* and sockets.
* <li> {@code StdIn} uses whitespace as the delimiter pattern
* that separates tokens.
* {@link Scanner} supports arbitrary delimiter patterns.
* <li> {@code StdIn} coerces the character-set encoding to UTF-8,
* which is the most widely used character encoding for Unicode.
* <li> {@code StdIn} coerces the locale to {@link Locale#US},
* for consistency with {@link StdOut}, {@link Double#parseDouble(String)},
* and floating-point literals.
* <li> {@code StdIn} has convenient methods for reading a single
* character; reading in sequences of integers, doubles, or strings;
* and reading in all of the remaining input.
* </ul>
* <p>
* Historical note: {@code StdIn} preceded {@code Scanner}; when
* {@code Scanner} was introduced, this class was re-implemented to use {@code Scanner}.
* <p>
* <b>Using standard input.</b>
* Standard input is a fundamental operating system abstraction on Mac OS X,
* Windows, and Linux.
* The methods in {@code StdIn} are <em>blocking</em>, which means that they
* will wait until you enter input on standard input.
* If your program has a loop that repeats until standard input is empty,
* you must signal that the input is finished.
* To do so, depending on your operating system and IDE,
* use either {@code <Ctrl-d>} or {@code <Ctrl-z>}, on its own line.
* If you are redirecting standard input from a file, you will not need
* to do anything to signal that the input is finished.
* <p>
* <b>Known bugs.</b>
* Java's UTF-8 encoding does not recognize the optional
* <a href = "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058">byte-order mask</a>.
* If the input begins with the optional byte-order mask, {@code StdIn}
* will have an extra character {@code \}{@code uFEFF} at the beginning.
* <p>
* <b>Reference.</b>
* For additional documentation,
* see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <em>Computer Science: An Interdisciplinary Approach</em>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
* @author David Pritchard
*/
public final class StdIn {
/*** begin: section (1 of 2) of code duplicated from In to StdIn. */
// assume Unicode UTF-8 encoding
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with System.out.
private static final Locale LOCALE = Locale.US;
// the default token separator; we maintain the invariant that this value
// is held by the scanner's delimiter between calls
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\p{javaWhitespace}+");
// makes whitespace significant
private static final Pattern EMPTY_PATTERN = Pattern.compile("");
// used to read the entire input
private static final Pattern EVERYTHING_PATTERN = Pattern.compile("\\A");
/*** end: section (1 of 2) of code duplicated from In to StdIn. */
private static Scanner scanner;
// it doesn't make sense to instantiate this class
private StdIn() { }
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from "public" to "public static"
/**
* Returns true if standard input is empty (except possibly for whitespace).
* Use this method to know whether the next call to {@link #readString()},
* {@link #readDouble()}, etc will succeed.
*
* @return {@code true} if standard input is empty (except possibly
* for whitespace); {@code false} otherwise
*/
public static boolean isEmpty() {
return !scanner.hasNext();
}
/**
* Returns true if standard input has a next line.
* Use this method to know whether the
* next call to {@link #readLine()} will succeed.
* This method is functionally equivalent to {@link #hasNextChar()}.
*
* @return {@code true} if standard input has more input (including whitespace);
* {@code false} otherwise
*/
public static boolean hasNextLine() {
return scanner.hasNextLine();
}
/**
* Returns true if standard input has more input (including whitespace).
* Use this method to know whether the next call to {@link #readChar()} will succeed.
* This method is functionally equivalent to {@link #hasNextLine()}.
*
* @return {@code true} if standard input has more input (including whitespace);
* {@code false} otherwise
*/
public static boolean hasNextChar() {
scanner.useDelimiter(EMPTY_PATTERN);
boolean result = scanner.hasNext();
scanner.useDelimiter(WHITESPACE_PATTERN);
return result;
}
/**
* Reads and returns the next line, excluding the line separator if present.
*
* @return the next line, excluding the line separator if present;
* {@code null} if no such line
*/
public static String readLine() {
String line;
try {
line = scanner.nextLine();
}
catch (NoSuchElementException e) {
line = null;
}
return line;
}
/**
* Reads and returns the next character.
*
* @return the next {@code char}
* @throws NoSuchElementException if standard input is empty
*/
public static char readChar() {
try {
scanner.useDelimiter(EMPTY_PATTERN);
String ch = scanner.next();
assert ch.length() == 1 : "Internal (Std)In.readChar() error!"
+ " Please contact the authors.";
scanner.useDelimiter(WHITESPACE_PATTERN);
return ch.charAt(0);
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'char' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads and returns the remainder of the input, as a string.
*
* @return the remainder of the input, as a string
* @throws NoSuchElementException if standard input is empty
*/
public static String readAll() {
if (!scanner.hasNextLine())
return "";
String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();
// not that important to reset delimeter, since now scanner is empty
scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway
return result;
}
/**
* Reads the next token from standard input and returns it as a {@code String}.
*
* @return the next {@code String}
* @throws NoSuchElementException if standard input is empty
*/
public static String readString() {
try {
return scanner.next();
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'String' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as an integer, and returns the integer.
*
* @return the next integer on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as an {@code int}
*/
public static int readInt() {
try {
return scanner.nextInt();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read an 'int' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attemps to read an 'int' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a double, and returns the double.
*
* @return the next double on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code double}
*/
public static double readDouble() {
try {
return scanner.nextDouble();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'double' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'double' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a float, and returns the float.
*
* @return the next float on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code float}
*/
public static float readFloat() {
try {
return scanner.nextFloat();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'float' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'float' value from standard input, "
+ "but there no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a long integer, and returns the long integer.
*
* @return the next long integer on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code long}
*/
public static long readLong() {
try {
return scanner.nextLong();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'long' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'long' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a short integer, and returns the short integer.
*
* @return the next short integer on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code short}
*/
public static short readShort() {
try {
return scanner.nextShort();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'short' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'short' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a byte, and returns the byte.
*
* @return the next byte on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code byte}
*/
public static byte readByte() {
try {
return scanner.nextByte();
}
catch (InputMismatchException e) {
String token = scanner.next();
throw new InputMismatchException("attempts to read a 'byte' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'byte' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads the next token from standard input, parses it as a boolean,
* and returns the boolean.
*
* @return the next boolean on standard input
* @throws NoSuchElementException if standard input is empty
* @throws InputMismatchException if the next token cannot be parsed as a {@code boolean}:
* {@code true} or {@code 1} for true, and {@code false} or {@code 0} for false,
* ignoring case
*/
public static boolean readBoolean() {
try {
String token = readString();
if ("true".equalsIgnoreCase(token)) return true;
if ("false".equalsIgnoreCase(token)) return false;
if ("1".equals(token)) return true;
if ("0".equals(token)) return false;
throw new InputMismatchException("attempts to read a 'boolean' value from standard input, "
+ "but the next token is \"" + token + "\"");
}
catch (NoSuchElementException e) {
throw new NoSuchElementException("attempts to read a 'boolean' value from standard input, "
+ "but no more tokens are available");
}
}
/**
* Reads all remaining tokens from standard input and returns them as an array of strings.
*
* @return all remaining tokens on standard input, as an array of strings
*/
public static String[] readAllStrings() {
// we could use readAll.trim().split(), but that's not consistent
// because trim() uses characters 0x00..0x20 as whitespace
String[] tokens = WHITESPACE_PATTERN.split(readAll());
if (tokens.length == 0 || tokens[0].length() > 0)
return tokens;
// don't include first token if it is leading whitespace
String[] decapitokens = new String[tokens.length-1];
for (int i = 0; i < tokens.length - 1; i++)
decapitokens[i] = tokens[i+1];
return decapitokens;
}
/**
* Reads all remaining lines from standard input and returns them as an array of strings.
* @return all remaining lines on standard input, as an array of strings
*/
public static String[] readAllLines() {
ArrayList<String> lines = new ArrayList<String>();
while (hasNextLine()) {
lines.add(readLine());
}
return lines.toArray(new String[lines.size()]);
}
/**
* Reads all remaining tokens from standard input, parses them as integers, and returns
* them as an array of integers.
* @return all remaining integers on standard input, as an array
* @throws InputMismatchException if any token cannot be parsed as an {@code int}
*/
public static int[] readAllInts() {
String[] fields = readAllStrings();
int[] vals = new int[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Integer.parseInt(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from standard input, parses them as longs, and returns
* them as an array of longs.
* @return all remaining longs on standard input, as an array
* @throws InputMismatchException if any token cannot be parsed as a {@code long}
*/
public static long[] readAllLongs() {
String[] fields = readAllStrings();
long[] vals = new long[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Long.parseLong(fields[i]);
return vals;
}
/**
* Reads all remaining tokens from standard input, parses them as doubles, and returns
* them as an array of doubles.
* @return all remaining doubles on standard input, as an array
* @throws InputMismatchException if any token cannot be parsed as a {@code double}
*/
public static double[] readAllDoubles() {
String[] fields = readAllStrings();
double[] vals = new double[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Double.parseDouble(fields[i]);
return vals;
}
//// end: section (2 of 2) of code duplicated from In to StdIn
// do this once when StdIn is initialized
static {
resync();
}
/**
* If StdIn changes, use this to reinitialize the scanner.
*/
private static void resync() {
setScanner(new Scanner(new java.io.BufferedInputStream(System.in), CHARSET_NAME));
}
private static void setScanner(Scanner scanner) {
StdIn.scanner = scanner;
StdIn.scanner.useLocale(LOCALE);
}
/**
* Reads all remaining tokens, parses them as integers, and returns
* them as an array of integers.
* @return all remaining integers, as an array
* @throws InputMismatchException if any token cannot be parsed as an {@code int}
* @deprecated Replaced by {@link #readAllInts()}.
*/
@Deprecated
public static int[] readInts() {
return readAllInts();
}
/**
* Reads all remaining tokens, parses them as doubles, and returns
* them as an array of doubles.
* @return all remaining doubles, as an array
* @throws InputMismatchException if any token cannot be parsed as a {@code double}
* @deprecated Replaced by {@link #readAllDoubles()}.
*/
@Deprecated
public static double[] readDoubles() {
return readAllDoubles();
}
/**
* Reads all remaining tokens and returns them as an array of strings.
* @return all remaining tokens, as an array of strings
* @deprecated Replaced by {@link #readAllStrings()}.
*/
@Deprecated
public static String[] readStrings() {
return readAllStrings();
}
/**
* Interactive test of basic functionality.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
StdOut.print("Type a string: ");
String s = StdIn.readString();
StdOut.println("Your string was: " + s);
StdOut.println();
StdOut.print("Type an int: ");
int a = StdIn.readInt();
StdOut.println("Your int was: " + a);
StdOut.println();
StdOut.print("Type a boolean: ");
boolean b = StdIn.readBoolean();
StdOut.println("Your boolean was: " + b);
StdOut.println();
StdOut.print("Type a double: ");
double c = StdIn.readDouble();
StdOut.println("Your double was: " + c);
StdOut.println();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,339 @@
/******************************************************************************
* Compilation: javac StdOut.java
* Execution: java StdOut
* Dependencies: none
*
* Writes data of various types to standard output.
*
******************************************************************************/
package algs4.util;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Locale;
/**
* This class provides methods for printing strings and numbers to standard output.
* <p>
* <b>Getting started.</b>
* To use this class, you must have {@code StdOut.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
* and add to your Java classpath or download
* <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdOut.java">StdOut.java</a>
* and put a copy in your working directory.
* <p>
* Here is an example program that uses {@code StdOut}:
* <pre>
* public class TestStdOut {
* public static void main(String[] args) {
* int a = 17;
* int b = 23;
* int sum = a + b;
* StdOut.println("Hello, World");
* StdOut.printf("%d + %d = %d\n", a, b, sum);
* }
* }
* </pre>
* <p>
* <b>Differences with System.out.</b>
* The behavior of {@code StdOut} is similar to that of {@link System#out},
* but there are a few technical differences:
* <ul>
* <li> {@code StdOut} coerces the character-set encoding to UTF-8,
* which is a standard character encoding for Unicode.
* <li> {@code StdOut} coerces the locale to {@link Locale#US},
* for consistency with {@link StdIn}, {@link Double#parseDouble(String)},
* and floating-point literals.
* <li> {@code StdOut} <em>flushes</em> standard output after each call to
* {@code print()} so that text will appear immediately in the terminal.
* </ul>
* <p>
* <b>Reference.</b>
* For additional documentation,
* see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <em>Computer Science: An Interdisciplinary Approach</em>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class StdOut {
// force Unicode UTF-8 encoding; otherwise it's system dependent
private static final String CHARSET_NAME = "UTF-8";
// assume language = English, country = US for consistency with StdIn
private static final Locale LOCALE = Locale.US;
// send output here
private static PrintWriter out;
// this is called before invoking any methods
static {
try {
out = new PrintWriter(new OutputStreamWriter(System.out, CHARSET_NAME), true);
}
catch (UnsupportedEncodingException e) {
System.out.println(e);
}
}
// don't instantiate
private StdOut() { }
/**
* Terminates the current line by printing the line-separator string.
*/
public static void println() {
out.println();
}
/**
* Prints an object to this output stream and then terminates the line.
*
* @param x the object to print
*/
public static void println(Object x) {
out.println(x);
}
/**
* Prints a boolean to standard output and then terminates the line.
*
* @param x the boolean to print
*/
public static void println(boolean x) {
out.println(x);
}
/**
* Prints a character to standard output and then terminates the line.
*
* @param x the character to print
*/
public static void println(char x) {
out.println(x);
}
/**
* Prints a double to standard output and then terminates the line.
*
* @param x the double to print
*/
public static void println(double x) {
out.println(x);
}
/**
* Prints an integer to standard output and then terminates the line.
*
* @param x the integer to print
*/
public static void println(float x) {
out.println(x);
}
/**
* Prints an integer to standard output and then terminates the line.
*
* @param x the integer to print
*/
public static void println(int x) {
out.println(x);
}
/**
* Prints a long to standard output and then terminates the line.
*
* @param x the long to print
*/
public static void println(long x) {
out.println(x);
}
/**
* Prints a short integer to standard output and then terminates the line.
*
* @param x the short to print
*/
public static void println(short x) {
out.println(x);
}
/**
* Prints a byte to standard output and then terminates the line.
* <p>
* To write binary data, see {@link BinaryStdOut}.
*
* @param x the byte to print
*/
public static void println(byte x) {
out.println(x);
}
/**
* Flushes standard output.
*/
public static void print() {
out.flush();
}
/**
* Prints an object to standard output and flushes standard output.
*
* @param x the object to print
*/
public static void print(Object x) {
out.print(x);
out.flush();
}
/**
* Prints a boolean to standard output and flushes standard output.
*
* @param x the boolean to print
*/
public static void print(boolean x) {
out.print(x);
out.flush();
}
/**
* Prints a character to standard output and flushes standard output.
*
* @param x the character to print
*/
public static void print(char x) {
out.print(x);
out.flush();
}
/**
* Prints a double to standard output and flushes standard output.
*
* @param x the double to print
*/
public static void print(double x) {
out.print(x);
out.flush();
}
/**
* Prints a float to standard output and flushes standard output.
*
* @param x the float to print
*/
public static void print(float x) {
out.print(x);
out.flush();
}
/**
* Prints an integer to standard output and flushes standard output.
*
* @param x the integer to print
*/
public static void print(int x) {
out.print(x);
out.flush();
}
/**
* Prints a long integer to standard output and flushes standard output.
*
* @param x the long integer to print
*/
public static void print(long x) {
out.print(x);
out.flush();
}
/**
* Prints a short integer to standard output and flushes standard output.
*
* @param x the short integer to print
*/
public static void print(short x) {
out.print(x);
out.flush();
}
/**
* Prints a byte to standard output and flushes standard output.
*
* @param x the byte to print
*/
public static void print(byte x) {
out.print(x);
out.flush();
}
/**
* Prints a formatted string to standard output, using the specified format
* string and arguments, and then flushes standard output.
*
*
* @param format the <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">format string</a>
* @param args the arguments accompanying the format string
*/
public static void printf(String format, Object... args) {
out.printf(LOCALE, format, args);
out.flush();
}
/**
* Prints a formatted string to standard output, using the locale and
* the specified format string and arguments; then flushes standard output.
*
* @param locale the locale
* @param format the <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">format string</a>
* @param args the arguments accompanying the format string
*/
public static void printf(Locale locale, String format, Object... args) {
out.printf(locale, format, args);
out.flush();
}
/**
* Unit tests some of the methods in {@code StdOut}.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// write to stdout
StdOut.println("Test");
StdOut.println(17);
StdOut.println(true);
StdOut.printf("%.6f\n", 1.0/7.0);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,674 @@
/******************************************************************************
* Compilation: javac StdRandom.java
* Execution: java StdRandom
* Dependencies: StdOut.java
*
* A library of static methods to generate pseudo-random numbers from
* different distributions (bernoulli, uniform, gaussian, discrete,
* and exponential). Also includes a method for shuffling an array.
*
*
* % java StdRandom 5
* seed = 1316600602069
* 59 16.81826 true 8.83954 0
* 32 91.32098 true 9.11026 0
* 35 10.11874 true 8.95396 3
* 92 32.88401 true 8.87089 0
* 72 92.55791 true 9.46241 0
*
* % java StdRandom 5
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
* % java StdRandom 5 1316600616575
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
*
* Remark
* ------
* - Relies on randomness of nextDouble() method in java.util.Random
* to generate pseudo-random numbers in [0, 1).
*
* - This library allows you to set and get the pseudo-random number seed.
*
* - See http://www.honeylocust.com/RngPack/ for an industrial
* strength random number generator in Java.
*
******************************************************************************/
package algs4.util;
import java.util.Random;
/**
* The {@code StdRandom} class provides static methods for generating
* random number from various discrete and continuous distributions,
* including uniform, Bernoulli, geometric, Gaussian, exponential, Pareto,
* Poisson, and Cauchy. It also provides method for shuffling an
* array or subarray and generating random permutations.
* <p>
* By convention, all intervals are half open. For example,
* <code>uniform(-1.0, 1.0)</code> returns a random number between
* <code>-1.0</code> (inclusive) and <code>1.0</code> (exclusive).
* Similarly, <code>shuffle(a, lo, hi)</code> shuffles the <code>hi - lo</code>
* elements in the array <code>a[]</code>, starting at index <code>lo</code>
* (inclusive) and ending at index <code>hi</code> (exclusive).
* <p>
* For additional documentation,
* see <a href="https://introcs.cs.princeton.edu/22library">Section 2.2</a> of
* <i>Computer Science: An Interdisciplinary Approach</i>
* by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class StdRandom {
private static Random random; // pseudo-random number generator
private static long seed; // pseudo-random number generator seed
// static initializer
static {
// this is how the seed was set in Java 1.4
seed = System.currentTimeMillis();
random = new Random(seed);
}
// don't instantiate
private StdRandom() { }
/**
* Sets the seed of the pseudo-random number generator.
* This method enables you to produce the same sequence of "random"
* number for each execution of the program.
* Ordinarily, you should call this method at most once per program.
*
* @param s the seed
*/
public static void setSeed(long s) {
seed = s;
random = new Random(seed);
}
/**
* Returns the seed of the pseudo-random number generator.
*
* @return the seed
*/
public static long getSeed() {
return seed;
}
/**
* Returns a random real number uniformly in [0, 1).
*
* @return a random real number uniformly in [0, 1)
*/
public static double uniform() {
return random.nextDouble();
}
/**
* Returns a random integer uniformly in [0, n).
*
* @param n number of possible integers
* @return a random integer uniformly between 0 (inclusive) and {@code n} (exclusive)
* @throws IllegalArgumentException if {@code n <= 0}
*/
public static int uniform(int n) {
if (n <= 0) throw new IllegalArgumentException("argument must be positive: " + n);
return random.nextInt(n);
}
/**
* Returns a random long integer uniformly in [0, n).
*
* @param n number of possible {@code long} integers
* @return a random long integer uniformly between 0 (inclusive) and {@code n} (exclusive)
* @throws IllegalArgumentException if {@code n <= 0}
*/
public static long uniform(long n) {
if (n <= 0L) throw new IllegalArgumentException("argument must be positive: " + n);
// https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long-
long r = random.nextLong();
long m = n - 1;
// power of two
if ((n & m) == 0L) {
return r & m;
}
// reject over-represented candidates
long u = r >>> 1;
while (u + m - (r = u % n) < 0L) {
u = random.nextLong() >>> 1;
}
return r;
}
///////////////////////////////////////////////////////////////////////////
// STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA
// THE STATIC METHODS ABOVE.
///////////////////////////////////////////////////////////////////////////
/**
* Returns a random real number uniformly in [0, 1).
*
* @return a random real number uniformly in [0, 1)
* @deprecated Replaced by {@link #uniform()}.
*/
@Deprecated
public static double random() {
return uniform();
}
/**
* Returns a random integer uniformly in [a, b).
*
* @param a the left endpoint
* @param b the right endpoint
* @return a random integer uniformly in [a, b)
* @throws IllegalArgumentException if {@code b <= a}
* @throws IllegalArgumentException if {@code b - a >= Integer.MAX_VALUE}
*/
public static int uniform(int a, int b) {
if ((b <= a) || ((long) b - a >= Integer.MAX_VALUE)) {
throw new IllegalArgumentException("invalid range: [" + a + ", " + b + ")");
}
return a + uniform(b - a);
}
/**
* Returns a random real number uniformly in [a, b).
*
* @param a the left endpoint
* @param b the right endpoint
* @return a random real number uniformly in [a, b)
* @throws IllegalArgumentException unless {@code a < b}
*/
public static double uniform(double a, double b) {
if (!(a < b)) {
throw new IllegalArgumentException("invalid range: [" + a + ", " + b + ")");
}
return a + uniform() * (b-a);
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability <em>p</em>.
*
* @param p the probability of returning {@code true}
* @return {@code true} with probability {@code p} and
* {@code false} with probability {@code 1 - p}
* @throws IllegalArgumentException unless {@code 0} &le; {@code p} &le; {@code 1.0}
*/
public static boolean bernoulli(double p) {
if (!(p >= 0.0 && p <= 1.0))
throw new IllegalArgumentException("probability p must be between 0.0 and 1.0: " + p);
return uniform() < p;
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability 1/2.
*
* @return {@code true} with probability 1/2 and
* {@code false} with probability 1/2
*/
public static boolean bernoulli() {
return bernoulli(0.5);
}
/**
* Returns a random real number from a standard Gaussian distribution.
*
* @return a random real number from a standard Gaussian distribution
* (mean 0 and standard deviation 1).
*/
public static double gaussian() {
// use the polar form of the Box-Muller transform
double r, x, y;
do {
x = uniform(-1.0, 1.0);
y = uniform(-1.0, 1.0);
r = x*x + y*y;
} while (r >= 1 || r == 0);
return x * Math.sqrt(-2 * Math.log(r) / r);
// Remark: y * Math.sqrt(-2 * Math.log(r) / r)
// is an independent random gaussian
}
/**
* Returns a random real number from a Gaussian distribution with mean &mu;
* and standard deviation &sigma;.
*
* @param mu the mean
* @param sigma the standard deviation
* @return a real number distributed according to the Gaussian distribution
* with mean {@code mu} and standard deviation {@code sigma}
*/
public static double gaussian(double mu, double sigma) {
return mu + sigma * gaussian();
}
/**
* Returns a random integer from a geometric distribution with success
* probability <em>p</em>.
* The integer represents the number of independent trials
* before the first success.
*
* @param p the parameter of the geometric distribution
* @return a random integer from a geometric distribution with success
* probability {@code p}; or {@code Integer.MAX_VALUE} if
* {@code p} is (nearly) equal to {@code 1.0}.
* @throws IllegalArgumentException unless {@code p >= 0.0} and {@code p <= 1.0}
*/
public static int geometric(double p) {
if (!(p >= 0)) {
throw new IllegalArgumentException("probability p must be greater than 0: " + p);
}
if (!(p <= 1.0)) {
throw new IllegalArgumentException("probability p must not be larger than 1: " + p);
}
// using algorithm given by Knuth
return (int) Math.ceil(Math.log(uniform()) / Math.log(1.0 - p));
}
/**
* Returns a random integer from a Poisson distribution with mean &lambda;.
*
* @param lambda the mean of the Poisson distribution
* @return a random integer from a Poisson distribution with mean {@code lambda}
* @throws IllegalArgumentException unless {@code lambda > 0.0} and not infinite
*/
public static int poisson(double lambda) {
if (!(lambda > 0.0))
throw new IllegalArgumentException("lambda must be positive: " + lambda);
if (Double.isInfinite(lambda))
throw new IllegalArgumentException("lambda must not be infinite: " + lambda);
// using algorithm given by Knuth
// see http://en.wikipedia.org/wiki/Poisson_distribution
int k = 0;
double p = 1.0;
double expLambda = Math.exp(-lambda);
do {
k++;
p *= uniform();
} while (p >= expLambda);
return k-1;
}
/**
* Returns a random real number from the standard Pareto distribution.
*
* @return a random real number from the standard Pareto distribution
*/
public static double pareto() {
return pareto(1.0);
}
/**
* Returns a random real number from a Pareto distribution with
* shape parameter &alpha;.
*
* @param alpha shape parameter
* @return a random real number from a Pareto distribution with shape
* parameter {@code alpha}
* @throws IllegalArgumentException unless {@code alpha > 0.0}
*/
public static double pareto(double alpha) {
if (!(alpha > 0.0))
throw new IllegalArgumentException("alpha must be positive: " + alpha);
return Math.pow(1 - uniform(), -1.0/alpha) - 1.0;
}
/**
* Returns a random real number from the Cauchy distribution.
*
* @return a random real number from the Cauchy distribution.
*/
public static double cauchy() {
return Math.tan(Math.PI * (uniform() - 0.5));
}
/**
* Returns a random integer from the specified discrete distribution.
*
* @param probabilities the probability of occurrence of each integer
* @return a random integer from a discrete distribution:
* {@code i} with probability {@code probabilities[i]}
* @throws IllegalArgumentException if {@code probabilities} is {@code null}
* @throws IllegalArgumentException if sum of array entries is not (very nearly) equal to {@code 1.0}
* @throws IllegalArgumentException unless {@code probabilities[i] >= 0.0} for each index {@code i}
*/
public static int discrete(double[] probabilities) {
if (probabilities == null) throw new IllegalArgumentException("argument array must not be null");
double EPSILON = 1.0E-14;
double sum = 0.0;
for (int i = 0; i < probabilities.length; i++) {
if (!(probabilities[i] >= 0.0))
throw new IllegalArgumentException("array entry " + i + " must be non-negative: " + probabilities[i]);
sum += probabilities[i];
}
if (sum > 1.0 + EPSILON || sum < 1.0 - EPSILON)
throw new IllegalArgumentException("sum of array entries does not approximately equal 1.0: " + sum);
// the for loop may not return a value when both r is (nearly) 1.0 and when the
// cumulative sum is less than 1.0 (as a result of floating-point roundoff error)
while (true) {
double r = uniform();
sum = 0.0;
for (int i = 0; i < probabilities.length; i++) {
sum = sum + probabilities[i];
if (sum > r) return i;
}
}
}
/**
* Returns a random integer from the specified discrete distribution.
*
* @param frequencies the frequency of occurrence of each integer
* @return a random integer from a discrete distribution:
* {@code i} with probability proportional to {@code frequencies[i]}
* @throws IllegalArgumentException if {@code frequencies} is {@code null}
* @throws IllegalArgumentException if all array entries are {@code 0}
* @throws IllegalArgumentException if {@code frequencies[i]} is negative for any index {@code i}
* @throws IllegalArgumentException if sum of frequencies exceeds {@code Integer.MAX_VALUE} (2<sup>31</sup> - 1)
*/
public static int discrete(int[] frequencies) {
if (frequencies == null) throw new IllegalArgumentException("argument array must not be null");
long sum = 0;
for (int i = 0; i < frequencies.length; i++) {
if (frequencies[i] < 0)
throw new IllegalArgumentException("array entry " + i + " must be non-negative: " + frequencies[i]);
sum += frequencies[i];
}
if (sum == 0)
throw new IllegalArgumentException("at least one array entry must be positive");
if (sum >= Integer.MAX_VALUE)
throw new IllegalArgumentException("sum of frequencies overflows an int");
// pick index i with probabilitity proportional to frequency
double r = uniform((int) sum);
sum = 0;
for (int i = 0; i < frequencies.length; i++) {
sum += frequencies[i];
if (sum > r) return i;
}
// can't reach here
assert false;
return -1;
}
/**
* Returns a random real number from an exponential distribution
* with rate &lambda;.
*
* @param lambda the rate of the exponential distribution
* @return a random real number from an exponential distribution with
* rate {@code lambda}
* @throws IllegalArgumentException unless {@code lambda > 0.0}
*/
public static double exp(double lambda) {
if (!(lambda > 0.0))
throw new IllegalArgumentException("lambda must be positive: " + lambda);
return -Math.log(1 - uniform()) / lambda;
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(Object[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(double[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(int[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
* @param a the array to shuffle
* @throws IllegalArgumentException if {@code a} is {@code null}
*/
public static void shuffle(char[] a) {
validateNotNull(a);
int n = a.length;
for (int i = 0; i < n; i++) {
int r = i + uniform(n-i); // between i and n-1
char temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
* @param a the array to shuffle
* @param lo the left endpoint (inclusive)
* @param hi the right endpoint (exclusive)
* @throws IllegalArgumentException if {@code a} is {@code null}
* @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}
*
*/
public static void shuffle(Object[] a, int lo, int hi) {
validateNotNull(a);
validateSubarrayIndices(lo, hi, a.length);
for (int i = lo; i < hi; i++) {
int r = i + uniform(hi-i); // between i and hi-1
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
* @param a the array to shuffle
* @param lo the left endpoint (inclusive)
* @param hi the right endpoint (exclusive)
* @throws IllegalArgumentException if {@code a} is {@code null}
* @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public static void shuffle(double[] a, int lo, int hi) {
validateNotNull(a);
validateSubarrayIndices(lo, hi, a.length);
for (int i = lo; i < hi; i++) {
int r = i + uniform(hi-i); // between i and hi-1
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
* @param a the array to shuffle
* @param lo the left endpoint (inclusive)
* @param hi the right endpoint (exclusive)
* @throws IllegalArgumentException if {@code a} is {@code null}
* @throws IllegalArgumentException unless {@code (0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public static void shuffle(int[] a, int lo, int hi) {
validateNotNull(a);
validateSubarrayIndices(lo, hi, a.length);
for (int i = lo; i < hi; i++) {
int r = i + uniform(hi-i); // between i and hi-1
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Returns a uniformly random permutation of <em>n</em> elements.
*
* @param n number of elements
* @throws IllegalArgumentException if {@code n} is negative
* @return an array of length {@code n} that is a uniformly random permutation
* of {@code 0}, {@code 1}, ..., {@code n-1}
*/
public static int[] permutation(int n) {
if (n < 0) throw new IllegalArgumentException("n must be non-negative: " + n);
int[] perm = new int[n];
for (int i = 0; i < n; i++)
perm[i] = i;
shuffle(perm);
return perm;
}
/**
* Returns a uniformly random permutation of <em>k</em> of <em>n</em> elements.
*
* @param n number of elements
* @param k number of elements to select
* @throws IllegalArgumentException if {@code n} is negative
* @throws IllegalArgumentException unless {@code 0 <= k <= n}
* @return an array of length {@code k} that is a uniformly random permutation
* of {@code k} of the elements from {@code 0}, {@code 1}, ..., {@code n-1}
*/
public static int[] permutation(int n, int k) {
if (n < 0) throw new IllegalArgumentException("n must be non-negative: " + n);
if (k < 0 || k > n) throw new IllegalArgumentException("k must be between 0 and n: " + k);
int[] perm = new int[k];
for (int i = 0; i < k; i++) {
int r = uniform(i+1); // between 0 and i
perm[i] = perm[r];
perm[r] = i;
}
for (int i = k; i < n; i++) {
int r = uniform(i+1); // between 0 and i
if (r < k) perm[r] = i;
}
return perm;
}
// throw an IllegalArgumentException if x is null
// (x can be of type Object[], double[], int[], ...)
private static void validateNotNull(Object x) {
if (x == null) {
throw new IllegalArgumentException("argument must not be null");
}
}
// throw an exception unless 0 <= lo <= hi <= length
private static void validateSubarrayIndices(int lo, int hi, int length) {
if (lo < 0 || hi > length || lo > hi) {
throw new IllegalArgumentException("subarray indices out of bounds: [" + lo + ", " + hi + ")");
}
}
/**
* Unit tests the methods in this class.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
if (args.length == 2) StdRandom.setSeed(Long.parseLong(args[1]));
double[] probabilities = { 0.5, 0.3, 0.1, 0.1 };
int[] frequencies = { 5, 3, 1, 1 };
String[] a = "A B C D E F G".split(" ");
StdOut.println("seed = " + StdRandom.getSeed());
for (int i = 0; i < n; i++) {
StdOut.printf("%2d ", uniform(100));
StdOut.printf("%8.5f ", uniform(10.0, 99.0));
StdOut.printf("%5b ", bernoulli(0.5));
StdOut.printf("%7.5f ", gaussian(9.0, 0.2));
StdOut.printf("%1d ", discrete(probabilities));
StdOut.printf("%1d ", discrete(frequencies));
StdOut.printf("%11d ", uniform(100000000000L));
StdRandom.shuffle(a);
for (String s : a)
StdOut.print(s);
StdOut.println();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,110 @@
/******************************************************************************
* Compilation: javac Stopwatch.java
* Execution: java Stopwatch n
* Dependencies: none
*
* A utility class to measure the running time (wall clock) of a program.
*
* % java8 Stopwatch 100000000
* 6.666667e+11 0.5820 seconds
* 6.666667e+11 8.4530 seconds
*
******************************************************************************/
package algs4.util;
/**
* The {@code Stopwatch} data type is for measuring
* the time that elapses between the start and end of a
* programming task (wall-clock time).
*
* See {@link StopwatchCPU} for a version that measures CPU time.
* For additional documentation,
* see <a href="https://algs4.cs.princeton.edu/14analysis">Section 1.4</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Stopwatch {
private final long start;
/**
* Initializes a new stopwatch.
*/
public Stopwatch() {
start = System.currentTimeMillis();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
* @return elapsed CPU time (in seconds) since the stopwatch was created
*/
public double elapsedTime() {
long now = System.currentTimeMillis();
return (now - start) / 1000.0;
}
/**
* Unit tests the {@code Stopwatch} data type.
* Takes a command-line argument {@code n} and computes the
* sum of the square roots of the first {@code n} positive integers,
* first using {@code Math.sqrt()}, then using {@code Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
Stopwatch timer1 = new Stopwatch();
double sum1 = 0.0;
for (int i = 1; i <= n; i++) {
sum1 += Math.sqrt(i);
}
double time1 = timer1.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum1, time1);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
Stopwatch timer2 = new Stopwatch();
double sum2 = 0.0;
for (int i = 1; i <= n; i++) {
sum2 += Math.pow(i, 0.5);
}
double time2 = timer2.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum2, time2);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,112 @@
/******************************************************************************
* Compilation: javac StopwatchCPU.java
* Execution: java StopwtachCPU n
* Dependencies: none
*
* A version of Stopwatch.java that measures CPU time on a single
* core or processor (instead of wall clock time).
*
* % java8 StopwatchCPU 100000000
* 6.666667e+11 (1.05 seconds)
* 6.666667e+11 (7.50 seconds)
*
******************************************************************************/
package algs4.util;
import java.lang.management.ThreadMXBean;
import java.lang.management.ManagementFactory;
/**
* The {@code StopwatchCPU} data type is for measuring
* the CPU time used during a programming task.
*
* See {@link Stopwatch} for a version that measures wall-clock time
* (the real time that elapses).
*
* @author Josh Hug
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class StopwatchCPU {
private static final double NANOSECONDS_PER_SECOND = 1_000_000_000;
private final ThreadMXBean threadTimer;
private final long start;
/**
* Initializes a new stopwatch.
*/
public StopwatchCPU() {
threadTimer = ManagementFactory.getThreadMXBean();
start = threadTimer.getCurrentThreadCpuTime();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
* @return elapsed CPU time (in seconds) since the stopwatch was created
*/
public double elapsedTime() {
long now = threadTimer.getCurrentThreadCpuTime();
return (now - start) / NANOSECONDS_PER_SECOND;
}
/**
* Unit tests the {@code StopwatchCPU} data type.
* Takes a command-line argument {@code n} and computes the
* sum of the square roots of the first {@code n} positive integers,
* first using {@code Math.sqrt()}, then using {@code Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
StopwatchCPU timer1 = new StopwatchCPU();
double sum1 = 0.0;
for (int i = 1; i <= n; i++) {
sum1 += Math.sqrt(i);
}
double time1 = timer1.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum1, time1);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
StopwatchCPU timer2 = new StopwatchCPU();
double sum2 = 0.0;
for (int i = 1; i <= n; i++) {
sum2 += Math.pow(i, 0.5);
}
double time2 = timer2.elapsedTime();
StdOut.printf("%e (%.2f seconds)\n", sum2, time2);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/

@ -0,0 +1,6 @@
package core.problem;
public abstract class Action {
public abstract void draw();
public abstract int stepCost();
}

@ -0,0 +1,143 @@
package core.problem;
import core.solver.Node;
import core.solver.heuristic.Predictor;
import java.util.ArrayList;
import java.util.Deque;
/**
*
* initialState
* goal
*/
public abstract class Problem {
//成员变量
protected State initialState;
protected State goal;
protected int size; //问题的规模15-puzzle为4寻路问题为Grid的边长野人传教士为野人与传教士的人数
public Problem(State initialState, State goal) {
this.initialState = initialState;
this.goal = goal;
}
public Problem(State initialState, State goal, int size) {
this(initialState, goal);
this.size = size;
}
public State getInitialState() {
return initialState;
}
public State getGoal() {
return goal;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void setInitialState(State initialState) {
this.initialState = initialState;
}
public void setGoal(State goal) {
this.goal = goal;
}
/**
*
* @return true; false
*
*/
public abstract boolean solvable();
/**
*
* @param predictor
* @return
*/
public final Node root(Predictor predictor) {
return new Node(initialState, null, null,
0, predictor.heuristics(initialState, goal));
}
/**
* node
* @param parent
* @param predictor
*
* @return parent
*/
public final Iterable<? extends Node> childNodes(Node parent, Predictor predictor) {
ArrayList<Node> nodes = new ArrayList<>();
//父结点的状态
State parentState = parent.getState();
//对于parentState上所有可能的action但有的不可行
for (Action action : parentState.actions()){
//如果父结点状态下的动作是可行的
if (applicable(parentState, action)){
//得到后继状态
State state = parentState.next(action);
//计算路径长度 = 父结点路径长度 + 进入后继状态所采取的动作的代价
int pathCost = parent.getPathCost() + stepCost(state, action);
//使用predictor对state与goal的距离进行估值
int heuristics = predictor.heuristics(state, goal);
//生成子结点
Node child = new Node(state, parent, action, pathCost, heuristics);
nodes.add(child);
}
}
return nodes;
}
/**
*
* @param state
* @param action Action
* @return
*/
public abstract int stepCost(State state, Action action);
/**
* stateaction
* @param state
* @param action
* @return truefalse
*/
protected abstract boolean applicable(State state, Action action);
/**
* state
*
* @param state
* @return truefalse
*/
public boolean goal(State state){
return state.equals(goal);
}
/**
*
* @param path
*/
public abstract void showSolution(Deque<Node> path);
/**
*
*/
public abstract void draw();
/**
*
* @param path
*/
public abstract void printPath(Deque<Node> path);
}

@ -0,0 +1,22 @@
package core.problem;
/**
*
*/
public abstract class State {
public abstract void draw(); // 在Console上输出该状态
/**
* action
* @param action action
* @return
*/
public abstract State next(Action action);
/**
* Action
* @return Action
*/
public abstract Iterable<? extends Action> actions();
}

@ -0,0 +1,85 @@
package core.runner;
import core.problem.Problem;
import core.problem.State;
import core.solver.Searcher;
import core.solver.heuristic.AbstractFrontier;
import core.solver.heuristic.BestFirstSearch;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import algs4.util.In;
import xu.problem.pathfinding.Position;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
/**
*
* problem
* 使Frontier
* 使 h
* IDA Star
*
*/
public abstract class EngineFeeder {
/**
* NPuzzle
* @param io
* @return NPuzzle
*/
public abstract ArrayList<Problem> getProblems(In io);
public abstract ArrayList<Problem> getProblems(Scanner scanner);
/**
* Frontier
* @param type
* @return 使Frontier
*/
public abstract AbstractFrontier getFrontier(EvaluationType type);
/**
* Predictor
* @param type
* @return
*/
public abstract Predictor getPredictor(HeuristicType type);
/**
* IdaStar
*/
public abstract Searcher getIdaStar();
/**
* Searcher
* @return
*/
public abstract Searcher getScoreSearcher();
/**
* AStar,
* 使AStar
*/
public Searcher getAStar(HeuristicType type){
//获取Frontier其Node以g(n)+h(n)的升序排列
AbstractFrontier frontier = getFrontier(EvaluationType.FULL);
//以HashSet作为Explored表
Set<State> explored = new HashSet<>();
//根据explored和frontier生成AStar引擎并使用类型为type的启发函数
return new BestFirstSearch(explored, frontier, Position.predictor(type));
}
/**
* Dijkstra
* @return Dijkstra
*/
public Searcher getDijkstra(){
//获取Frontier其Node以g(n)+h(n)的升序排列
AbstractFrontier frontier = getFrontier(EvaluationType.PATH_COST);
//以HashSet作为Explored表
Set<State> explored = new HashSet<>();
//根据explored和frontier生成AStar引擎并使用曼哈顿距离作为启发函数
return new BestFirstSearch(explored, frontier, (state, goal) -> 0);
}
}

@ -0,0 +1,16 @@
package core.runner;
public enum HeuristicType {
//Npuzzle的启发函数
MISPLACED, // 不在位将牌
MANHATTAN, // 曼哈顿距离
DISJOINT_PATTERN,
//PathFinding的启发函数 (8方向的情况)
PF_EUCLID, // 欧几里得距离
PF_MANHATTAN, // 8方向移动时不是admissible的
PF_GRID, // 尽可能走对角线,然后平行走,>= EUCLID
//野人传教士问题
MC_HARMONY //去掉野人会吃人的约束
}

@ -0,0 +1,8 @@
package core.runner;
public enum ProblemType {
NPUZZLE, // NPuzzle问题
PATHFINDING, // 寻路问题
SLIDING_BLOCKS, // 滑动积木块问题
MISSIONARY_AND_CARNIVAL //野人传教士问题
}

@ -0,0 +1,98 @@
package core.runner;
import core.problem.Problem;
import core.solver.Node;
import algs4.util.In;
import core.solver.heuristic.BestFirstSearch;
import g08.problem.npuzzle.DecodeTalker;
import g08.problem.npuzzle.FeederG08;
import g08.problem.npuzzle.Npuzzle;
import xu.problem.pathfinding.FeederXu;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Scanner;
public class SearchRunner {
public static void xuPathfinding()
{
//从文件中读入问题的实例,寻路问题
In problemInput = new In("resources/pathfinding.txt");
//生成一个具体的EngineFeederFeederXu引擎饲养员徐老师:)
EngineFeeder feeder = new FeederXu();
//feeder从文件获取所有问题实例
ArrayList<Problem> problems = feeder.getProblems(problemInput);
//从Feeder获取所使用的搜索引擎 AStar
BestFirstSearch astar = (BestFirstSearch) feeder.getScoreSearcher();
for (Problem problem : problems){
//使用AStar引擎求解问题
Deque<Node> path = astar.search(problem);
//解的可视化
problem.showSolution(path);
//仅打印路径
problem.printPath(path);
System.out.println(astar.expandedNode());
System.out.println();
}
System.out.println("==============================================================");
//从Feeder获取所使用的搜索引擎 Dijkstra
BestFirstSearch dijkstra = (BestFirstSearch) feeder.getDijkstra();
for (Problem problem : problems){
//使用AStar引擎求解问题
Deque<Node> path = dijkstra.search(problem);
//解的可视化
problem.showSolution(path);
//仅打印路径
problem.printPath(path);
System.out.println(dijkstra.expandedNode());
System.out.println();
}
}
public static void nPuzzle()
{
System.out.println("Npuzzle");
//从文件中读入问题的实例npuzzle问题
In problemInput = new In("resources/npuzzle.txt");
EngineFeeder feeder = new FeederG08();
ArrayList<Problem> problems = feeder.getProblems(problemInput);
for(Problem problem:problems)
{
if(problem.solvable())
{
System.out.println("solvable");
DecodeTalker decodeTalker = new DecodeTalker(problem.getInitialState(),problem.getGoal());
if(decodeTalker.ida_star())
{
decodeTalker.draw();
}
}
}
}
public static void main(String[] args) {
System.out.println("1. 寻路问题");
System.out.println("2. Npuzzle");
System.out.println("请输入:");
Scanner sc = new Scanner(System.in);
int flag = sc.nextInt();
if(flag==1)
{
xuPathfinding();
}
else if(flag==2)
{
nPuzzle();
}
}
}

@ -0,0 +1,146 @@
package core.solver;
import core.problem.Action;
import core.problem.State;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import java.util.Comparator;
import java.util.EnumMap;
import static core.solver.heuristic.EvaluationType.*;
public final class Node{
//不考虑路径代价的Node
/**
*
* @param state
* @param parent
* @param action Action
*/
public Node(State state, Node parent, Action action){
this(state, parent, action, 0, 0);
}
//考虑路径代价的Node
/**
*
* @param state
* @param parent
* @param action Action
* @param pathCost
* @param heuristic
*/
public Node(State state, Node parent, Action action, int pathCost, int heuristic) {
super();
this.state = state;
this.parent = parent;
this.action = action;
this.pathCost = pathCost;
this.heuristic = heuristic;
}
/**
*
* @param action使Action
* @param predictorh
* @param goal: h
* @return
*/
public Node childNode(Action action, Predictor predictor, State goal) {
return new Node(state.next(action), this, action,
pathCost + action.stepCost(),
predictor.heuristics(state, goal));
}
private final State state; // the state in the state space to which the node corresponds
private final Node parent; // the node in the search tree which generated this node
public Action getAction() {
return action;
}
private final Action action; // the action that was applied to the parent to generate the node
private final int pathCost; // the cost of the path from the initial state to this node
private final int heuristic; // estimated cost of the cheapest path from the state of this node to a goal state
//返回当前Node的f值 f = g + h
public int evaluation()
{
return pathCost + heuristic;
}
public State getState() {
return state;
}
public Node getParent() {
return parent;
}
public int getPathCost() {
return pathCost;
}
public int getHeuristic() {
return heuristic;
}
/**
* Node
*/
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Node) {
Node another = (Node) obj;
//两个Node对象的状态相同则认为是相同的
return this.getState().equals(another.getState());
}
return false;
}
public void draw() {
System.out.println(this);
}
/**
*
*/
private static final EnumMap<EvaluationType, Comparator<Node>> evaluators = new EnumMap<>(EvaluationType.class);
//枚举映射表的初始化
static{
//f = g + h FULL
evaluators.put(FULL,
Comparator.comparingInt(Node::evaluation)
);
//g PATH_COST
evaluators.put(PATH_COST,
Comparator.comparingInt(Node::getPathCost)
);
//h HEURISTIC
evaluators.put(HEURISTIC,
Comparator.comparingInt(Node::getHeuristic)
);
}
/**
*
* @param type
* @return
*/
public static Comparator<Node> evaluator(EvaluationType type) {
return evaluators.get(type);
}
@Override
public String toString() {
return "[" + state.toString() + "⬅" + "[" + parent.getState().toString() + ", " + action.toString() + "], " + pathCost + ", " + heuristic + "]";
}
}

@ -0,0 +1,29 @@
package core.solver;
import core.problem.Problem;
import java.util.ArrayDeque;
import java.util.Deque;
public interface Searcher {
/**
* @problem
* @return null
*/
Deque<Node> search(Problem problem);
/**
*
* @param node
* @return
*/
default Deque<Node> generatePath(Node node) {
Deque<Node> stack = new ArrayDeque<>();
while (node.getParent() != null) {
stack.push(node);
node = node.getParent();
}
return stack;
}
}

@ -0,0 +1,4 @@
package core.solver.blinded;
public class BreadthFirstSearch {
}

@ -0,0 +1,5 @@
package core.solver.blinded;
public class DepthFirstSearch {
}

@ -0,0 +1,66 @@
package core.solver.heuristic;
import core.problem.State;
import core.solver.Node;
import java.util.*;
/**
* AbstractQueue
* core.solver.Node
*/
public abstract class AbstractFrontier extends AbstractQueue<Node> {
public AbstractFrontier(Comparator<Node> evaluator) {
this.evaluator = evaluator;
}
public Comparator<Node> getEvaluator() {
return evaluator;
}
// 节点优先级比较器在Node类中定义了三个不同的比较器Dijkstra, Greedy Best-First, and Best-First
// 不同的选择对应不同的算法。
protected final Comparator<Node> evaluator;
/**
* Frontier s
* @param s
* @return s
* null
*/
protected abstract Node getNode(State s);
/**
* Frontiernode
*
* @param node
* @return true
*/
public final boolean discardOrReplace(Node node){
if (node == null)
throw new NullPointerException();
//结点node是否出现在frontier中; null: not revisited
Node oldNode = getNode(node.getState());
//如果oldNode为null则当前结点node的状态不在Frontier中那么肯定在explored表中
// 又因为h函数是consistent的所以discard
//如果oldNode不为null则在oldNode已经在Frontier中并且旧的估值比新的大即新生成的结点更好
if (oldNode != null && evaluator.compare(oldNode, node) > 0){
//则,用新节点替换旧节点
replace(oldNode, node);
}
return true;
}
/**
* e oldNode
*
* @param oldNode
* @param newNode
*/
public void replace(Node oldNode, Node newNode) {
this.remove(oldNode);
this.add(newNode);
}
}

@ -0,0 +1,78 @@
package core.solver.heuristic;
import java.util.*;
import core.problem.Problem;
import core.problem.State;
import core.solver.*;
/**
* final
*/
public final class BestFirstSearch implements Searcher {
//已经访问过的节点集合
private final Set<State> explored;
//还未扩展的节点队列
private final AbstractFrontier frontier;
private final Predictor predictor;
/**
*
* @param explored Set hashSet
* @param frontier Nodefrontier
*/
public BestFirstSearch(Set<State> explored, AbstractFrontier frontier, Predictor predictor) {
this.explored = explored;
this.frontier = frontier;
this.predictor = predictor;
}
@Override
public Deque<Node> search(Problem problem)
{
//如果可直接判断问题是否可解无解时直接返回解路径为null
if (!problem.solvable()){
return null;
}
frontier.clear();
explored.clear();
//搜索树的根节点
Node root = problem.root(predictor);
this.frontier.add(root);
while (true) {
if (frontier.isEmpty())
return null; //失败
Node node = frontier.poll(); //choose the lowest-cost node in frontier
//如果已经到达目标状态,
if (problem.goal(node.getState())) {
return generatePath(node);
}
//将当前结点放入explored表中
explored.add(node.getState());
for (Node child : problem.childNodes(node, predictor)) {
// 如果新扩展的节点没有在Explored和Fringe中出现过。
// 因为两个node的状态相同则视为二者相同equals函数
// 所以contains函数判断frontier中是否存在跟child的状态相同的结点
if (!explored.contains(child.getState()) && !frontier.contains(child)) {
frontier.offer(child);
}
else {
//child出现在Explored或Fringe中
//在启发函数满足单调条件的前提下如果child是出现在Explored表里的节点肯定不在Fringe中
//而且到达这个节点的新路径肯定不会比旧路径更优
frontier.discardOrReplace(child);
}
}
}
}
public int expandedNode(){
return explored.size();
}
}

@ -0,0 +1,11 @@
package core.solver.heuristic;
/**
* Best-First
*
*/
public enum EvaluationType {
FULL,
PATH_COST,
HEURISTIC //对于不同的问题,启发策略又可能又多种。
}

@ -0,0 +1,18 @@
package core.solver.heuristic;
import core.problem.State;
/**
*
*
*/
public interface Predictor {
/**
*
* @param
* state
* goal
* @return
*/
int heuristics(State state, State goal);
}

@ -0,0 +1,197 @@
package g08.problem.npuzzle;
import core.problem.State;
import java.util.ArrayList;
import java.util.Stack;
/**
* ClassName : DecodeTalker //类名
* Description : //描述
* Author : WLS //作者
* Date: 2021-04-16 09:21 //时间
*/
public class DecodeTalker {
private char dire[] = {'E','W','S','N'};
private int dx[] = {0, 0, 1, -1};
private int dy[] = {1, -1, 0, 0};
private int[] curindex = new int[2];
private Stack<int[]> curs=new Stack<>();
private int[][] inze;
private int[][] maze;
private int[][] goze;
private int size;
private Stack<Character> path=new Stack<>();
public DecodeTalker(State init, State goal)
{
char[] s1=init.toString().toCharArray();
char[] s2=goal.toString().toCharArray();
size = (int)Math.sqrt(s1.length);
maze=new int[size][size];
goze=new int[size][size];
inze=new int[size][size];
int t=0;
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
inze[i][j]=s1[t]-'0';
maze[i][j]=s1[t]-'0';
goze[i][j]=s2[t]-'0';
t++;
if(inze[i][j]==0)
{
curindex[0]=i;
curindex[1]=j;
}
}
}
}
public int h()
{
int res = 0;
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
if(maze[i][j]==0)continue;
for(int i2=0;i2<size;i2++)
{
for(int j2=0;j2<size;j2++)
{
if(goze[i2][j2]==maze[i][j])
{
res+=Math.abs(i2-i)+Math.abs(j2-j);
}
}
}
}
}
return res;
}
public boolean dfs(int g, int prev, int f)
{
int h = h();
if(h==0)
{
return true;
}
if(g+h>f)
return false;
for(int i=0;i<4;i++)
{
if((i^1)==prev)continue;
int x = curindex[0]+dx[i];
int y = curindex[1]+dy[i];
if(x<0||x>=size||y<0||y>=size)continue;
//int[] temp=curindex;
curs.push(new int[]{curindex[0], curindex[1]});
path.push(dire[i]);
int t=maze[x][y];
maze[x][y]=maze[curindex[0]][curindex[1]];
maze[curindex[0]][curindex[1]]=t;
curindex[0]=x;
curindex[1]=y;
if(dfs(++g,i,f))
{
return true;
}
curindex=curs.pop();
int t2=maze[x][y];
maze[x][y]=maze[curindex[0]][curindex[1]];
maze[curindex[0]][curindex[1]]=t2;
path.pop();
}
return false;
}
public boolean ida_star()
{
for(int f=h();f<41;f++)
{
if(dfs(0,-1,f))
{
return true;
}
}
return false;
}
public void draw()
{
String S="";
for(Character c : path)
{
S+=c;
}
System.out.println(S);
int x=0,y=0;
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
if(inze[i][j]==0)
{
x=i;
y=j;
break;
}
}
}
for(Character c : path)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
System.out.printf("%-3d",inze[i][j]);
}
System.out.println();
}
if(c == 'E')
{
System.out.println("(E,→)");
int t=inze[x][y];
inze[x][y]=inze[x][y+1];
inze[x][y+1]=t;
y++;
}
else if(c == 'W')
{
System.out.println("(W,←)");
int t=inze[x][y];
inze[x][y]=inze[x][y-1];
inze[x][y-1]=t;
y--;
}
else if(c == 'S')
{
System.out.println("(S,↓)");
int t=inze[x][y];
inze[x][y]=inze[x+1][y];
inze[x+1][y]=t;
x++;
}
else
{
System.out.println("(N,↑)");
int t=inze[x][y];
inze[x][y]=inze[x-1][y];
inze[x-1][y]=t;
x--;
}
}
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
System.out.printf("%-3d",inze[i][j]);
}
System.out.println();;
}
}
}

@ -0,0 +1,83 @@
package g08.problem.npuzzle;
import algs4.util.In;
import core.problem.Problem;
import core.runner.EngineFeeder;
import core.runner.HeuristicType;
import core.solver.Node;
import core.solver.Searcher;
import core.solver.heuristic.AbstractFrontier;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import g08.solver.heuristic.LinkedFrontier;
import java.util.ArrayList;
import java.util.Scanner;
/**
* ClassName : FeederG08 //类名
* Description : //描述
* Author : WLS //作者
* Date: 2021-04-15 10:26 //时间
*/
public class FeederG08 extends EngineFeeder {
@Override
public ArrayList<Problem> getProblems(In io) {
ArrayList<Problem> problems = new ArrayList<>();
while(io.hasNextLine())
{
int size = io.readInt();
int[][] initial = new int[size][size];
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
initial[i][j] = io.readInt();
}
}
int[][] goal = new int[size][size];
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
goal[i][j] = io.readInt();
}
}
Maze init = new Maze(size, initial);
Maze go = new Maze(size, goal);
//init.draw();
//System.out.println();
//go.draw();
//System.out.println("===============================");
Npuzzle problem = new Npuzzle(init,go,size);
problems.add(problem);
}
return problems;
}
@Override
public ArrayList<Problem> getProblems(Scanner scanner) {
return null;
}
@Override
public AbstractFrontier getFrontier(EvaluationType type) {
return new LinkedFrontier(Node.evaluator(type));
}
@Override
public Predictor getPredictor(HeuristicType type) {
return null;
}
@Override
public Searcher getIdaStar() {
return null;
}
@Override
public Searcher getScoreSearcher() {
return getAStar(HeuristicType.MANHATTAN);
}
}

@ -0,0 +1,65 @@
package g08.problem.npuzzle;
import core.problem.Action;
import core.problem.State;
/**
* ClassName : Maze //类名
* Description : //描述
* Author : WLS //作者
* Date: 2021-04-15 10:39 //时间
*/
public class Maze extends State {
private int size;
private int[][] maze;
public Maze(){}
public Maze(int s, int[][] m)
{
size = s;
maze = m;
}
public int[][] getMaze()
{
return maze;
}
@Override
public void draw() {
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
System.out.printf("%-3d",maze[i][j]);
}
System.out.println();
}
}
@Override
public State next(Action action) {
return null;
}
@Override
public Iterable<? extends Action> actions() {
return null;
}
@Override
public String toString()
{
String string = "";
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
string+=maze[i][j];
}
}
return string;
}
}

@ -0,0 +1,28 @@
package g08.problem.npuzzle;
/**
* ClassName : Nod //类名
* Description : //描述
* Author : WLS //作者
* Date: 2021-04-16 15:02 //时间
*/
public class Nod {
private char move;
private int num;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public char getMove() {
return move;
}
public void setMove(char move) {
this.move = move;
}
}

@ -0,0 +1,82 @@
package g08.problem.npuzzle;
import core.problem.Action;
import core.problem.Problem;
import core.problem.State;
import core.solver.Node;
import java.util.Deque;
/**
* ClassName : Npuzzle //类名
* Description : //描述
* Author : WLS //作者
* Date: 2021-04-15 11:01 //时间
*/
public class Npuzzle extends Problem {
public Npuzzle(State initialState, State goal)
{
super(initialState, goal);
}
public Npuzzle(State initialState, State goal, int size)
{
super(initialState, goal, size);
}
@Override
public boolean solvable() {
int cnt = 0;
char[] init = initialState.toString().toCharArray();
char[] go = goal.toString().toCharArray();
for(int i = 0;i<size*size;i++)
{
for(int j=0;j<size*size;j++)
{
if(init[i]=='0'||init[j]=='0')
continue;
if(init[i]>init[j])
{
cnt++;
}
}
}
if(cnt%2==1)
{
System.out.println("unsolvable");
return false;
}
return true;
}
@Override
public int stepCost(State state, Action action) {
return 0;
}
@Override
protected boolean applicable(State state, Action action) {
return false;
}
@Override
public void showSolution(Deque<Node> path) {
System.out.println("showSolution");
}
@Override
public void draw() {
initialState.draw();
System.out.println();
goal.draw();
System.out.println("=======================");
}
@Override
public void printPath(Deque<Node> path) {
System.out.println("printPath");
}
}

@ -0,0 +1,89 @@
package g08.solver.heuristic;
import core.problem.State;
import core.solver.Node;
import core.solver.heuristic.AbstractFrontier;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
/**
* LinkedListFrontier
*/
public class LinkedFrontier extends AbstractFrontier {
//底层实现用的是LinkedList
private final LinkedList<Node> nodeList = new LinkedList<>();
public LinkedFrontier(Comparator<Node> evaluator) {
super(evaluator);
}
/**
* Frontier s
*
* @param s
* @return s
* null
*/
@Override
protected Node getNode(State s) {
for (Node node: nodeList){
if (node.getState().equals(s)){
return node;
}
}
return null;
}
@Override
public boolean remove(Object o) {
return nodeList.remove(o);
}
/**
* node
* @param node
* @return true
*/
@Override
public boolean add(Node node) {
int j = 0;
for (Node value : nodeList) {
if (evaluator.compare(value, node) >= 0) {
break;
}
j++;
}
nodeList.add(j, node);
return true;
}
@Override
public Iterator<Node> iterator() {
return nodeList.iterator();
}
@Override
public int size() {
return nodeList.size();
}
@Override
public boolean offer(Node node) {
return this.add(node);
}
@Override
public Node poll() {
return nodeList.poll();
}
@Override
public Node peek() {
return nodeList.peek();
}
}

@ -0,0 +1,60 @@
package xu.problem.pathfinding;
import java.util.EnumMap;
public enum Direction {
N('↑'), //北
NE('↗'), //东北
E('→'), //东
SE('↘'), //东南
S('↓'), //南
SW('↙'), //西南
W('←'), //西
NW('↖'); //西北
Direction(char symbol){
this.symbol = symbol;
}
private final char symbol;
public char symbol(){
return symbol;
}
//各个方向移动的代价直线为10斜线为14
private static final EnumMap<Direction, Integer> DIRECTION_COST = new EnumMap<>(Direction.class);
static{
int scale = Position.SCALE;
int diagonal = (int) (scale * Position.ROOT2);
DIRECTION_COST.put(N, scale);
DIRECTION_COST.put(NE, diagonal);
DIRECTION_COST.put(E, scale);
DIRECTION_COST.put(SE, diagonal);
DIRECTION_COST.put(S, scale);
DIRECTION_COST.put(SW, diagonal);
DIRECTION_COST.put(W, scale);
DIRECTION_COST.put(NW, diagonal);
}
//各个方向移动的坐标位移量
private static final EnumMap<Direction, int[]> DIRECTION_OFFSET = new EnumMap<>(Direction.class);
static{
//列号(或横坐标)增加量;行号(或纵坐标)增加量
DIRECTION_OFFSET.put(N, new int[]{0, -1});
DIRECTION_OFFSET.put(NE, new int[]{1, -1});
DIRECTION_OFFSET.put(E, new int[]{1, 0});
DIRECTION_OFFSET.put(SE, new int[]{1, 1});
DIRECTION_OFFSET.put(S, new int[]{0, 1});
DIRECTION_OFFSET.put(SW, new int[]{-1, 1});
DIRECTION_OFFSET.put(W, new int[]{-1, 0});
DIRECTION_OFFSET.put(NW, new int[]{-1, -1});
}
public static int[] offset(Direction dir){
return DIRECTION_OFFSET.get(dir);
}
public static int cost(Direction dir){
return DIRECTION_COST.get(dir);
}
}

@ -0,0 +1,109 @@
package xu.problem.pathfinding;
import algs4.util.In;
import core.problem.Problem;
import core.problem.State;
import core.runner.EngineFeeder;
import core.runner.HeuristicType;
import core.solver.Node;
import core.solver.Searcher;
import core.solver.heuristic.AbstractFrontier;
import core.solver.heuristic.BestFirstSearch;
import core.solver.heuristic.EvaluationType;
import core.solver.heuristic.Predictor;
import xu.solver.heuristic.LinkedFrontier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
/**
* EngineFeeder
*/
public class FeederXu extends EngineFeeder {
/**
* NPuzzle
*
* @param io
* @return NPuzzle
*/
@Override
public ArrayList<Problem> getProblems(In io) {
ArrayList<Problem> problems = new ArrayList<>();
//地图的大小
int size = io.readInt();
//读入地图
GridType[][] grids = new GridType[size][];
for (int i = 0; i < size; i++){
grids[i] = new GridType[size];
for (int j = 0; j < size; j++){
int cellType = io.readInt();
grids[i][j] = GridType.values()[cellType];
}
}
while (io.hasNextLine()){
//读入初始状态
int row = io.readInt();
int col = io.readInt();
Position initialState = new Position(row, col);
//读入目标状态
row = io.readInt();
col = io.readInt();
Position goal = new Position(row, col);
//生成寻路问题的实例,并设置其地图
PathFinding problem = new PathFinding(initialState, goal, size);
problem.setGrids(grids);
//添加到问题列表
problems.add(problem);
}
return problems;
}
@Override
public ArrayList<Problem> getProblems(Scanner scanner) {
return null;
}
/**
* Frontier
*
* @param type
* @return 使Frontier
*/
@Override
public AbstractFrontier getFrontier(EvaluationType type) {
return new LinkedFrontier(Node.evaluator(type));
}
/**
* Predictor
*
* @param type
* @return
*/
@Override
public Predictor getPredictor(HeuristicType type) {
return Position.predictor(type);
}
/**
* IdaStar
*/
@Override
public Searcher getIdaStar() {
return null;
}
/**
* Searcher
*
* @return
*/
@Override
public Searcher getScoreSearcher() {
return getAStar(HeuristicType.PF_GRID);
}
}

@ -0,0 +1,23 @@
package xu.problem.pathfinding;
public enum GridType {
EMPTY('0'), // 空地
GRASS('#'), // 草地通过的代价高普通代价的2倍
//MUDDY, // 泥地通过代价为3倍
WALL('*'); // 石墙,无法通过
private final char symbol;
GridType(char symbol){
this.symbol = symbol;
}
public char symbol(){
return symbol;
}
@Override
public String toString() {
return symbol + "";
}
}

@ -0,0 +1,43 @@
package xu.problem.pathfinding;
import core.problem.Action;
public class Move extends Action {
private final Direction direction;
public Move(Direction direction) {
this.direction = direction;
}
public Direction getDirection() {
return direction;
}
@Override
public void draw() {
System.out.println(toString());
}
@Override
public int stepCost() {
return Direction.cost(direction);
}
@Override
public String toString() {
return direction.symbol() + "";
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Move) {
Move another = (Move) obj;
//两个Node对象的状态相同则认为是相同的
return this.direction.equals(another.direction);
}
return false;
}
}

@ -0,0 +1,146 @@
package xu.problem.pathfinding;
import core.problem.Action;
import core.problem.Problem;
import core.problem.State;
import core.solver.Node;
import java.util.Deque;
/**
*
*/
public class PathFinding extends Problem {
//地图信息
GridType[][] grids;
public PathFinding(State initialState, State goal) {
super(initialState, goal);
}
public PathFinding(State initialState, State goal, int size) {
super(initialState, goal, size);
grids = new GridType[size][size];
}
public GridType[][] getGrids() {
return grids;
}
public void setGrids(GridType[][] grids) {
for (int i = 0; i < size; i++){
System.arraycopy(grids[i], 0, this.grids[i], 0, size);
}
}
/**
*
* true
* @return true; false
*/
@Override
public boolean solvable() {
return true;
}
@Override
public int stepCost(State state, Action action) {
Position position = (Position) state ;
GridType type = grids[position.getRow() - 1][position.getCol() - 1];
if (type == GridType.EMPTY)
return action.stepCost();
if (type == GridType.GRASS)
return action.stepCost() * 5;
return Integer.MIN_VALUE;
}
@Override
protected boolean applicable(State state, Action action) {
int[] offsets = Direction.offset(((Move)action).getDirection());
int row = ((Position)state).getRow() + offsets[1];
int col = ((Position)state).getCol() + offsets[0];
return row > 0 && row <= size &&
col > 0 && col <= size &&
grids[row - 1][col - 1] != GridType.WALL;
}
@Override
public void showSolution(Deque<Node> path) {
//将地图转换为字符数组
char[][] grids = new char[size][];
for (int i = 0; i < size; i++){
grids[i] = new char[size];
for (int j = 0; j < size; j++) {
grids[i][j] = this.grids[i][j].symbol();
}
}
//标记起点
int row = ((Position)initialState).getRow();
int col = ((Position)initialState).getCol();
grids[row - 1][col - 1] = '@';
//和终点
row = ((Position)goal).getRow();
col = ((Position)goal).getCol();
grids[row - 1][col - 1] = '&';
//打印寻路问题。
System.out.println(initialState + "→" + goal);
//将解路径中的动作符号写入字符数组grids
for (Node node : path) {
Position p = (Position) node.getState();
Move move = (Move) node.getAction();
Direction d = move.getDirection();
grids[p.getRow() - 1][p.getCol() - 1] = d.symbol();
}
//打印字符数组
drawGrid(grids);
}
private void drawGrid(char[][] grids) {
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++) {
System.out.print(grids[i][j] + " ");
}
System.out.println();
}
}
/**
*
*
*/
@Override
public void draw() {
System.out.println(initialState + "→" + goal);
for (GridType[] rows : grids){
for (GridType type : rows){
System.out.print(type.symbol() + " ");
}
System.out.println();
}
}
/**
*
* @param path
*/
@Override
public void printPath(Deque<Node> path) {
if (path == null){
System.out.println("No Solution.");
return;
}
for (Node node : path) {
Move move = (Move) node.getAction();
System.out.print(move.getDirection().name() + " ");
}
System.out.println();
}
@Override
public String toString() {
return super.toString();
}
}

@ -0,0 +1,107 @@
package xu.problem.pathfinding;
import java.util.ArrayList;
import java.util.Comparator;
import static java.util.Comparator.*;
public class Point implements Comparable<Point>{
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
private int x;
private int y;
@Override
public String toString() {
return "(" + x + "," + y + ")";
}
public static final Comparator<Point> RowColComparator = naturalOrder();
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Point){
Point p = (Point) obj;
return this.x == p.x && this.y == p.y;
}
return false;
}
@Override
public int hashCode() {
return x << 3 | y;
}
//根据x坐标比较
public static final Comparator<Point> TestComparator = comparingInt(arg0 -> arg0.x);
//根据到原点的曼哈顿距离进行比较
public static final Comparator<Point> ManhattanComparator = comparingInt(arg0 -> arg0.manhattan(new Point(0, 0)));
/**
* p
* @param p p
* @return p
*/
public int manhattan(Point p){
return Math.abs(this.x - p.x) + Math.abs(this.y - p.y);
}
/**
* p
* @param p p
* @return p
*/
public double euclid(Point p){
int x = this.x - p.x;
int y = this.y - p.y;
return Math.sqrt(x * x + y * y);
}
/**
*
*/
@Override
public int compareTo(Point p) {
if (this.x == p.x)
return this.y - p.y;
return this.x - p.x;
}
public static void main(String[] args) {
ArrayList<Point> treeset = new ArrayList<>();
Point p = new Point(3, 5);
treeset.add(p);
p = new Point(4, 5);
treeset.add(p);
p = new Point(2, 7);
treeset.add(p);
p = new Point(3, 7);
treeset.add(p);
p = new Point(3, 1);
treeset.add(p);
treeset.sort(ManhattanComparator);
for (Point point : treeset) {
System.out.println(point);
}
}
}

@ -0,0 +1,132 @@
package xu.problem.pathfinding;
import core.problem.Action;
import core.problem.State;
import core.runner.HeuristicType;
import core.solver.Node;
import core.solver.heuristic.Predictor;
import java.util.ArrayList;
import java.util.EnumMap;
/**
* PathFinding
*
*/
public class Position extends State {
public static final int SCALE = 10; //单元格的边长
public static final double ROOT2 = 1.4; //2的平方根
//可移动的方向:四个方向或者八个方向
private static final int MOVETYPE = 1; //八个方向移动
private static final Direction[][] directions = new Direction[2][];
static{
//四个方向移动
directions[0] = new Direction[]{Direction.N, Direction.E, Direction.S, Direction.W};
//八个方向移动
directions[1] = Direction.values();
}
//机器人在场地中的位置
private final Point point;
public Position(int row, int col) {
this.point = new Point(row, col);
}
@Override
public void draw() {
System.out.println(this);
}
/**
* action
*
* @param action action
* @return
*/
@Override
public State next(Action action) {
//当前Action所带来的位移量
Direction dir = ((Move)action).getDirection();
int[] offsets = Direction.offset(dir);
//生成新状态所在的点
int col = getCol() + offsets[0];
int row = getRow() + offsets[1];
return new Position(row, col);
}
@Override
public Iterable<? extends Action> actions() {
ArrayList<Move> moves = new ArrayList<>();
for (Direction d : directions[MOVETYPE])
moves.add(new Move(d));
return moves;
}
//枚举映射,存放不同类型的启发函数
private static final EnumMap<HeuristicType, Predictor> predictors = new EnumMap<>(HeuristicType.class);
static{
predictors.put(HeuristicType.PF_EUCLID,
(state, goal) -> ((Position)state).euclid((Position)goal));
predictors.put(HeuristicType.PF_MANHATTAN,
(state, goal) -> ((Position)state).manhattan((Position)goal));
predictors.put(HeuristicType.PF_GRID,
(state, goal) -> ((Position)state).gridDistance((Position)goal));
}
public static Predictor predictor(HeuristicType type){
return predictors.get(type);
}
//两个点之间的Grid距离尽量走对角线
private int gridDistance(Position goal) {
int width = Math.abs(this.getCol() - goal.getCol());
int height = Math.abs(this.getRow() - goal.getRow());
if (width > height) {
return (width - height) * SCALE + height * (int) (SCALE * ROOT2);
}
else{
return (height - width) * SCALE + width * (int) (SCALE * ROOT2);
}
}
//两个点之间的曼哈顿距离乘以SCALE
private int manhattan(Position goal) {
return this.point.manhattan(goal.point) * SCALE;
}
//两个点之间的欧几里德距离
private int euclid(Position goal) {
return (int) (this.point.euclid(goal.point) * SCALE);
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Position ) {
Position another = (Position) obj;
//两个Node对象的状态相同则认为是相同的
return this.point.equals(another.point);
}
return false;
}
@Override
public int hashCode() {
return point.hashCode();
}
@Override
public String toString() {
return point.toString();
}
public int getRow() {
return point.getX();
}
public int getCol() {
return point.getY();
}
}

@ -0,0 +1,89 @@
package xu.solver.heuristic;
import core.problem.State;
import core.solver.Node;
import core.solver.heuristic.AbstractFrontier;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Collection;
/**
* LinkedListFrontier
*/
public class LinkedFrontier extends AbstractFrontier {
//底层实现用的是LinkedList
private final LinkedList<Node> nodeList = new LinkedList<>();
public LinkedFrontier(Comparator<Node> evaluator) {
super(evaluator);
}
/**
* Frontier s
*
* @param s
* @return s
* null
*/
@Override
protected Node getNode(State s) {
for (Node node: nodeList){
if (node.getState().equals(s)){
return node;
}
}
return null;
}
@Override
public boolean remove(Object o) {
return nodeList.remove(o);
}
/**
* node
* @param node
* @return true
*/
@Override
public boolean add(Node node) {
int j = 0;
for (Node value : nodeList) {
if (evaluator.compare(value, node) >= 0) {
break;
}
j++;
}
nodeList.add(j, node);
return true;
}
@Override
public Iterator<Node> iterator() {
return nodeList.iterator();
}
@Override
public int size() {
return nodeList.size();
}
@Override
public boolean offer(Node node) {
return this.add(node);
}
@Override
public Node poll() {
return nodeList.poll();
}
@Override
public Node peek() {
return nodeList.peek();
}
}

@ -0,0 +1,29 @@
package xu.problem.pathfinding;
import algs4.util.In;
import core.problem.Problem;
import core.runner.EngineFeeder;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
class PathFeederTest {
@Test
void getProblems() {
//生成一个具体的EngineFeederFeederXu引擎饲养员徐老师:)
EngineFeeder feeder = new FeederXu();
//从文件中读入问题的实例NPuzzle问题
In problemInput = new In("resources/pathfinding.txt");
//feeder从文件获取所有问题实例
ArrayList<Problem> problems = feeder.getProblems(problemInput);
for (Problem problem : problems){
problem.draw();
}
}
}

@ -0,0 +1,28 @@
package xu.problem.pathfinding;
import algs4.util.In;
import core.problem.Problem;
import core.runner.EngineFeeder;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.*;
class PathFindingTest {
@Test
void applicable() {
//生成一个具体的EngineFeederFeederXu引擎饲养员徐老师:)
EngineFeeder feeder = new FeederXu();
//从文件中读入问题的实例NPuzzle问题
In problemInput = new In("resources/pathfinding.txt");
//feeder从文件获取所有问题实例
ArrayList<Problem> problems = feeder.getProblems(problemInput);
Position position = new Position(7, 4);
assertFalse(((PathFinding)problems.get(0)).applicable(position, new Move(Direction.S)));
assertTrue(((PathFinding)problems.get(0)).applicable(position, new Move(Direction.E)));
}
}

@ -0,0 +1,20 @@
package xu.problem.pathfinding;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PositionTest {
@Test
void next() {
Position position = new Position(5, 6);
assertEquals(position.next(new Move(Direction.S)), new Position(6, 6));
Position next = (Position) position.next(new Move(Direction.E)); // (5,7)
assertEquals(next, new Position(5, 7));
assertEquals(next.next(new Move(Direction.N)), new Position(4, 7));
assertEquals(next.next(new Move(Direction.W)), new Position(5, 6));
}
}

@ -0,0 +1,65 @@
package xu.solver.heuristic;
import core.problem.State;
import core.solver.Node;
import core.solver.heuristic.EvaluationType;
import xu.problem.pathfinding.Direction;
import xu.problem.pathfinding.Move;
import xu.problem.pathfinding.Point;
import xu.problem.pathfinding.Position;
import static org.junit.jupiter.api.Assertions.*;
class LinkedFrontierTest {
@org.junit.jupiter.api.Test
void offer() {
LinkedFrontier frontier = new LinkedFrontier(Node.evaluator(EvaluationType.FULL));
State position = new Position(4, 4);
Node parent = new Node(position, null, null, 0, 15);
position = new Position(5, 5);
Node node = new Node(position, parent, new Move(Direction.SE), 0, 15);
frontier.offer(node);
position = new Position(5, 6);
node = new Node(position, node, new Move(Direction.S), 1, 13);
frontier.offer(node);
position = new Position(6, 6);
node = new Node(position, node, new Move(Direction.E), 2, 13);
frontier.offer(node);
position = new Position(7, 6);
node = new Node(position, node, new Move(Direction.E), 3, 9);
frontier.offer(node);
for (Node node1: frontier){
System.out.println(node1);
}
System.out.println();
position = new Position(9, 6);
node = new Node(position, node, new Move(Direction.E), 2, 13);
System.out.println(frontier.getNode(node.getState()));
position = new Position(6, 6);
node = new Node(position, node, new Move(Direction.W), 22, 13);
System.out.println(frontier.contains(node));
System.out.println();
position = new Position(5, 6);
node = new Node(position, node, new Move(Direction.S), 3, 10);
frontier.discardOrReplace(node);
for (Node node1: frontier){
System.out.println(node1);
}
System.out.println();
while (!frontier.isEmpty()){
frontier.poll().draw();
}
}
}
Loading…
Cancel
Save