Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Lothar Buchholz | 84dbcf81ee | 5 years ago |
Lothar Buchholz | 2656ded38f | 5 years ago |
@ -0,0 +1 @@
|
|||||||
|
buy-and-sell-n-times
|
@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GitSharedSettings">
|
||||||
|
<option name="FORCE_PUSH_PROHIBITED_PATTERNS">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -1,20 +1,62 @@
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.util.stream.IntStream;
|
||||||
import java.math.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template code to help you parse the standard input
|
|
||||||
* according to the problem statement.
|
|
||||||
**/
|
|
||||||
class Solution {
|
class Solution {
|
||||||
|
|
||||||
public static void main( String[] args ) {
|
public static void main( String[] args ) {
|
||||||
Scanner in = new Scanner( System.in );
|
// read values with in.next...() methods
|
||||||
// read values with in.next...() methods
|
var scanner = new Scanner( System.in );
|
||||||
|
var sellCount = scanner.nextInt();
|
||||||
|
var prices = scanner.tokens()
|
||||||
|
.mapToInt( Integer::valueOf )
|
||||||
|
.toArray();
|
||||||
|
|
||||||
// code your solution here
|
// Write result with System.out.println()
|
||||||
|
System.out.println( maxProfits( sellCount, prices ));
|
||||||
|
}
|
||||||
|
|
||||||
|
// code your solution here
|
||||||
|
// 0 - 1 | ... | x-sellCount - x --> 0 - x-1 | ... | x-1 - x
|
||||||
|
private static int maxProfits( int sellCount, int[] prices ) {
|
||||||
|
return IntStream.range( 0, sellCount )
|
||||||
|
.parallel()
|
||||||
|
.map( sale -> {
|
||||||
|
// recursion end condition
|
||||||
|
if ( sellCount == 1 ) {
|
||||||
|
return maxProfit( prices );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return IntStream.range( 2, prices.length )
|
||||||
|
.parallel()
|
||||||
|
.map( index -> {
|
||||||
|
var firstRange = Arrays.copyOfRange( prices, 0, index );
|
||||||
|
final int max1 = maxProfit( firstRange );
|
||||||
|
|
||||||
|
var secondRange = Arrays.copyOfRange( prices, index - 1,
|
||||||
|
prices.length
|
||||||
|
);
|
||||||
|
// reduce range sizes recursively
|
||||||
|
final int max2 = maxProfits( sellCount - 1, secondRange );
|
||||||
|
|
||||||
|
return max1 + max2;
|
||||||
|
})
|
||||||
|
.max().orElse( 0 );
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.max().orElse( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int maxProfit( int[] prices ) {
|
||||||
|
return IntStream.range( 0, prices.length )
|
||||||
|
.map( index -> {
|
||||||
|
var range = Arrays.copyOfRange( prices, Math.min( index + 1, prices.length - 1 ),
|
||||||
|
prices.length
|
||||||
|
);
|
||||||
|
int max = IntStream.of( range ).max().orElse( 0 );
|
||||||
|
// difference between current price and future maximum
|
||||||
|
return max - prices[index];
|
||||||
|
})
|
||||||
|
.max().orElse( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
// Write result with System.out.println()
|
|
||||||
System.out.println( "value" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||||
|
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static java.lang.System.currentTimeMillis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on TimingExtension from JUnit 5 user guide, and BenchmarkExtension from Nicolai Parlog
|
||||||
|
* https://github.com/CodeFX-org/demo-junit-5/blob/master/src/main/java/org/codefx/demo/junit5/BenchmarkExtension.java
|
||||||
|
*/
|
||||||
|
public class BenchmarkExtension implements BeforeAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, AfterAllCallback {
|
||||||
|
|
||||||
|
private static final Namespace NAMESPACE = Namespace.create( BenchmarkExtension.class );
|
||||||
|
private static final Logger LOGGER = Logger.getLogger( BenchmarkExtension.class.getName() );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeAll( ExtensionContext context ) {
|
||||||
|
context.getStore( NAMESPACE ).put( context.getRequiredTestClass(), currentTimeMillis() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterAll( ExtensionContext context ) {
|
||||||
|
long launchTime = context.getStore( NAMESPACE ).get( context.getRequiredTestClass(), long.class );
|
||||||
|
long elapsedTime = currentTimeMillis() - launchTime;
|
||||||
|
report( "Test class", context, elapsedTime );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTestExecution( ExtensionContext context ) {
|
||||||
|
context.getStore( NAMESPACE ).put( context.getRequiredTestMethod(), currentTimeMillis() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTestExecution( ExtensionContext context ) {
|
||||||
|
long launchTime = context.getStore( NAMESPACE ).get( context.getRequiredTestMethod(), long.class );
|
||||||
|
long elapsedTime = currentTimeMillis() - launchTime;
|
||||||
|
report( "Test", context, elapsedTime );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void report( String unit, ExtensionContext context, long elapsedTime ) {
|
||||||
|
String message = String.format( "%s '%s' took %d ms.", unit, context.getDisplayName(), elapsedTime );
|
||||||
|
context.publishReportEntry( "Benchmark", message );
|
||||||
|
LOGGER.info( message );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,77 +1,23 @@
|
|||||||
import java.io.*;
|
import com.github.stefanbirkner.systemlambda.SystemLambda;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.CsvFileSource;
|
import org.junit.jupiter.params.provider.CsvFileSource;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@ExtendWith( BenchmarkExtension.class )
|
||||||
class SolutionTest {
|
class SolutionTest {
|
||||||
|
|
||||||
static long totalDuration;
|
@ParameterizedTest
|
||||||
|
@CsvFileSource( resources = "testdata.csv" )
|
||||||
@BeforeAll
|
void main( final String sellCount, final String input, final String expected ) throws Exception {
|
||||||
static void beforeAll() {
|
String output = SystemLambda.tapSystemOutNormalized( () ->
|
||||||
totalDuration = 0;
|
SystemLambda.withTextFromSystemIn( sellCount + " " + input )
|
||||||
}
|
.execute( () -> Solution.main( new String[0] ))
|
||||||
|
);
|
||||||
@AfterAll
|
|
||||||
static void afterAll() {
|
|
||||||
System.out.println( String.format( "All solutions took %01d.%03d secs", totalDuration / 1000, totalDuration % 1000 ));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvFileSource( resources = "testdata.csv", numLinesToSkip = 1 )
|
|
||||||
void main( final String sellCount, final String input, final String expected ) throws IOException {
|
|
||||||
// keep original streams
|
|
||||||
InputStream oldIn = System.in;
|
|
||||||
PrintStream oldOut = System.out;
|
|
||||||
PrintStream oldErr = System.err;
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
try {
|
|
||||||
redirectStreams(
|
|
||||||
new ByteArrayInputStream( (sellCount + " " + input).getBytes( UTF_8 )),
|
|
||||||
new PrintStream( bos, true, UTF_8 ),
|
|
||||||
new PrintStream( new ByteArrayOutputStream(), true, UTF_8 )
|
|
||||||
);
|
|
||||||
|
|
||||||
// start time tracking
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
Solution.main( new String[0] );
|
|
||||||
|
|
||||||
// stop time tracking
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
|
||||||
totalDuration += duration;
|
|
||||||
|
|
||||||
// restore streams
|
|
||||||
redirectStreams( oldIn, oldOut, oldErr );
|
|
||||||
|
|
||||||
System.out.println( String.format( "Solution took %01d.%03d secs", duration / 1000, duration % 1000 ));
|
|
||||||
|
|
||||||
try (BufferedReader chk = new BufferedReader( new InputStreamReader( new ByteArrayInputStream( bos.toByteArray() ), UTF_8 ))) {
|
|
||||||
String[] expectedLines = expected.split( "\\s*[|]\\s*" );
|
|
||||||
|
|
||||||
int lineCount = 0;
|
assertEquals( expected, StringUtils.chomp( output.trim() ));
|
||||||
String line;
|
}
|
||||||
for ( ; (line = chk.readLine()) != null; lineCount++ ) {
|
|
||||||
assertEquals( expectedLines[ lineCount ], line );
|
|
||||||
}
|
|
||||||
assertEquals( expectedLines.length, lineCount );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
// restore streams
|
|
||||||
redirectStreams( oldIn, oldOut, oldErr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void redirectStreams( final InputStream input, final PrintStream output, final PrintStream error ) {
|
|
||||||
System.setIn( input );
|
|
||||||
System.setOut( output );
|
|
||||||
System.setErr( error );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.github.stefanbirkner.systemlambda;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Code that should be executed by on of the methods of {@link SystemLambda}.
|
||||||
|
* This code may throw an {@link Exception}. Therefore we cannot use
|
||||||
|
* {@link Runnable}.
|
||||||
|
*/
|
||||||
|
public interface Statement {
|
||||||
|
/**
|
||||||
|
* Execute the statement.
|
||||||
|
*
|
||||||
|
* @throws Exception the statement may throw an arbitrary exception.
|
||||||
|
*/
|
||||||
|
void execute() throws Exception;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
Loading…
Reference in New Issue