11
\$\begingroup\$

This is a follow-up of CodeGolf - Ignore the noise #1 the only problem being that Barry has made things even worse for us. Lets see what happened

Update

I've added code to create random input and expected output because I'm not that good at explaining what I want, and I guess that sometimes words are more misleading than code (isn't that always?)

Description

Another method in Dumb Corp's API gives us the current price a provider is giving us for an item, the optimal price we would be making maximum sales with and the tendency of that price compared to previous prices as a string UP or DOWN. We need to decide if we should remove the item from the shop or wait.

Input

80,90,UP
150,100,DOWN
65,65,UP
1618,1618,DOWN
840,1200,DOWN
54,12,UP
30,1,UP

For a huge input sample demo with expected output, put the following code (js) in your browsers console and it should output valid random input for testing.

var output = "";
var result = "";

for(i=10;i--;){
  var currentPrice = Math.floor(Math.random() * 10000) + 1;
  var optimalPrice = Math.floor(Math.random() * 10000) + 1;
  var tendency = Math.round(Math.random())?"UP":"DOWN";
  var tresult = "WAIT\n";

  if((currentPrice > optimalPrice && tendency == "UP") ||
     (currentPrice < optimalPrice && tendency == "DOWN")){
       tresult = "STOP\n";
     }

  output +=currentPrice+","+optimalPrice+","+tendency+"\n";
  result +=tresult;
}
console.log(output);
console.log(result);

As always we will have a variable G as our input, however if your language makes it easier for you to simply read the input, that's also fine. The format is constant, and follow the format int,int,string

Desired Output

You're the brains of this operation, Barry should be doing this calculation on the server, but we can't count on him as you should know. You need to output WAIT if the tendency is towards the optimal price, or STOP if the tendency is towards loses.

In other words, with the 80,90,UP as input, we know that there is a product with current price of 80 and optimal price of 90 with a tendency to rise up, so we should WAIT. On the other hand, 840,1200,DOWN means the product price is going down and our optimal price is higher, so we should stop losses by outputting STOP.

If the two prices are identical, output WAIT regardless of the tendency.

Each product in a new line, single word per line:

WAIT
WAIT
WAIT
WAIT
STOP
STOP
STOP

Please, when possible, provide a way of verifying that your code is working since we can't all know just by looking at the syntax. As always, use as few characters as possible and remember that you're not competing against other languages necessarily, your competing against languages with similar syntax

\$\endgroup\$
  • \$\begingroup\$ Your test data isn't terribly useful without expected results. \$\endgroup\$ – Not that Charles May 19 '15 at 14:19
  • \$\begingroup\$ @NotthatCharles: I'm pretty sure the block in the Desired Output section of the post is the expected result of the test data in the Input section. \$\endgroup\$ – Alex A. May 19 '15 at 14:23
  • \$\begingroup\$ I meant the "huge input sample" \$\endgroup\$ – Not that Charles May 19 '15 at 14:25
  • \$\begingroup\$ I realice now that it wasn't really helpful, updated the code to provide expected output. \$\endgroup\$ – Juan Cortés May 19 '15 at 14:30
  • 5
    \$\begingroup\$ Is there any reason why you prefer scoring in characters? The default around here is bytes (in an existing encoding of the participant's choice). With characters you just get people compressing their code by encoding it in Unicode characters and things like that. (Whatever your choice, don't change it for this challenge now, but you might want to keep it in mind for future challenges.) \$\endgroup\$ – Martin Ender May 19 '15 at 15:27

12 Answers 12

6
\$\begingroup\$

CJam, 31 29 27 characters

"㫅㍸ꕆ敟鸢Ꝓ約䢫솓儓隆뻨"2G#b128b:c~

This is just an encoded version of the following code (in order to make use of the scoring by characters):

r{',/:~3<)(f*~<"STOP""WAIT"?Nr}h

Run all test cases here.

There might be a way to shorten this by encoding STOP and WAIT, but I'm quite happy with the rest.

Explanation

The code is surrounded by a loop which reads on line at a time, processes it, then pushes a newline, and reads the next line... The loop terminates once r returns an empty string (i.e. after all lines have been processed). That's this bit:

r{ ... Nr}h

As for processing each line, I'm making use of the fact that upper case letters are variables in CJam, so I can eval some of the input.

',/:~3<)(f*~<"STOP""WAIT"?
',/                        e# Split the input on commas.
   :~                      e# Eval each of the three resulting strings. The first two
                           e# will yield the prices, the third will dump a bunch of
                           e# values corresponding to the variables DNOPUW in the array.
     3<                    e# Truncate to three elements, so we only get the prices and
                           e# the values corresponding to U (0) and D (13).
       )(                  e# Slices off that variable value and decrement it, to get
                           e# something negative for UP and positive for DOWN.
         f*                e# Multiply both numbers by that value. So if we had UP then
                           e# both numbers will be negative now, otherwise they'll just
                           e# be scaled without affecting their relative size.
           ~<              e# Unwrap the array and check which element is larger.
             "STOP""WAIT"? e# Select the desired output string based on this boolean.

So the catch is that for UP we invert the relative sizes of the prices, so that we can cover all cases with a single inequality at the end.

\$\endgroup\$
  • \$\begingroup\$ I've requested clarification from the OP and he said the code should work for several lines of input. The shortest way to achieve this should be this: "㫅㍸ꕆ敟鸢Ꝓ約䢫솓儓隆뻨"2G#b128b:c~ \$\endgroup\$ – Dennis May 19 '15 at 14:53
  • \$\begingroup\$ @Dennis Ugh, scoring by characters... thanks. \$\endgroup\$ – Martin Ender May 19 '15 at 15:27
7
\$\begingroup\$

Perl, 35

#!perl -pl
/,/;$_=$`-$'&&$`>$'^/D/?STOP:WAIT

Test me.

\$\endgroup\$
4
\$\begingroup\$

Perl, 77 73 bytes

while(<>){@p=split",";print($p[0]<$p[1]and$p[2]=~/D/?"STOP":"WAIT")."\n"}

Here's how it works:

  • while(<>) parses every line.
  • @p=split"," splits it by every comma. It's using the default Perl operator, $_ (which is where the line is stored.)
  • print (ternary) determines what to print.
  • $p[0]<$p[1]and$p[2]=~/D/ asks if the current price is less than the price we want, and it's going down (by checking for a D.)
  • (condition)?(if):(else) is the ternary operator.
  • If our condition earlier matched, it'll output STOP. Otherwise, it'll output WAIT.

I'm assuming there is no trailing newline on the input - a trailing newline produces an extra WAIT.

Thanks to Alex A. for helping me save 4 bytes!

\$\endgroup\$
  • \$\begingroup\$ Granted it's been quite a while since I've used Perl, but does it have to be and? Can you use & or something? \$\endgroup\$ – Alex A. May 19 '15 at 14:21
  • \$\begingroup\$ @AlexA. I'm not sure why, but && behaves strangely. I tried using it, and it said there was an "unmatched <>". \$\endgroup\$ – ASCIIThenANSI May 19 '15 at 14:22
  • \$\begingroup\$ Huh. Weird. Oh well. Nice solution. \$\endgroup\$ – Alex A. May 19 '15 at 14:28
  • \$\begingroup\$ Can you do a single call to print and just do something like print((condition)?"STOP":"WAIT")."\n"? \$\endgroup\$ – Alex A. May 19 '15 at 14:40
  • \$\begingroup\$ @AlexA. Huh, did not know you could do that. Thanks! \$\endgroup\$ – ASCIIThenANSI May 19 '15 at 14:43
4
\$\begingroup\$

C, 85

c;main(i,j){for(;scanf("%d,%d,%c%*s",&i,&j,&c)>0;)puts(i-j&&i>j^c<70?"STOP":"WAIT");}

Test me.

\$\endgroup\$
3
\$\begingroup\$

R, 95 108

R and strings, not really friends:)

eval(parse(t=sub("U","<",sub("D",">",gsub("(.*),(.*),(.).*","cat(if(\\1\\3=\\2)'WAIT\n'else'STOP\n')",G)))))

Input is the character vector G then changes each string into an if statement that is evaluated.

Edit Messed up my interpretation of the rules. Fix cost a few characters.

> G=c(
+     '80,90,UP',
+     '150,100,DOWN',
+     '65,65,UP',
+     '1618,1618,DOWN',
+     '840,1200,DOWN',
+     '54,12,UP',
+     '30,1,UP'
+ )
> eval(parse(t=sub("U","<",sub("D",">",gsub("(.*),(.*),(.).*","cat(if(\\1\\3=\\2)'WAIT\n'else'STOP\n')",G)))))
WAIT
WAIT
WAIT
WAIT
STOP
STOP
STOP
>
\$\endgroup\$
  • \$\begingroup\$ Why do the last two return "wait"? They should give "stop". \$\endgroup\$ – Oebele May 20 '15 at 8:12
  • \$\begingroup\$ @Oebele I misunderstood the rules. It wasn't the clear for higher current prices descending. Will fix soon \$\endgroup\$ – MickyT May 20 '15 at 8:52
3
\$\begingroup\$

Ruby - 89 Chars

G.split.map{|a|b,c,d=a.split(?,);puts (b.to_i>=c.to_i)^(e=d[2])&&(b!=c||e)?'STOP':'WAIT'}

RubyFiddle

With help from to bluetorange!

\$\endgroup\$
  • \$\begingroup\$ Is this correct for the new equal test cases? I also tried something like this, but that failed for one of those test cases. \$\endgroup\$ – Oebele May 19 '15 at 13:11
  • \$\begingroup\$ @Oebele didn't see that ... not sure whether they were added after my original but I've added the = now thanks :) \$\endgroup\$ – RichieAHB May 19 '15 at 13:15
  • \$\begingroup\$ Wait - why did I myself do a complex workaround taking many bytes instead of adding = which I knew was also a possibility... Time to fix! \$\endgroup\$ – Oebele May 19 '15 at 13:17
  • \$\begingroup\$ Does this account for case 1618,1618,DOWN ? \$\endgroup\$ – nderscore May 19 '15 at 16:42
  • \$\begingroup\$ Perhaps I'm stupid, but I don't get this code. It seems to me that for each of the 3 comma-separated values of each line, it does something with the 1st, 2nd, and 4th character and prints WAIT or STOP? Using a.split.map{..} prints 3 WAIT or STOP for each input line. Did you mean to do sth. like b,c,d=a.split(?,)? Also, !b[3][2] is shorter than b[3]=='UP', but I think that it should be b[2]? Comparing strings with >= requires attention, as "9">="77" is true. The default input line separator is \n, so you could use split without arguments. ?\n is shorter than '\n'. \$\endgroup\$ – blutorange May 21 '15 at 12:36
3
\$\begingroup\$

Python 3, 89 84 82 bytes

for l in G:a,b,c=l.split(',');print('WSATIOTP'[a==b or(int(a)<int(b))^(c<'U')::2])

Explanation:

for l in G:                                   #For every line in G:
           a,b,c=l.split(',');                #Split the line into three strings.
                              print()         #Print the contained expression.

'WSATIOTP'                                    #'WAIT' and 'STOP' interleaved.
          [                              ::2] #Select every other character.
                or                            #If either expression is true, pick 'WAIT'
           a==b
                  (             )^(     )     #Select 'WAIT' if exactly one is true.
                   int(a)<int(b)              #If first number < second number.
                                   c<'U'      #If c is 'DOWN'
\$\endgroup\$
  • \$\begingroup\$ Care to explain it? \$\endgroup\$ – Juan Cortés May 20 '15 at 23:01
  • \$\begingroup\$ @JuanCortés Added explanation. \$\endgroup\$ – TheNumberOne May 21 '15 at 16:07
  • 1
    \$\begingroup\$ Beautiful, I love it! \$\endgroup\$ – Juan Cortés May 21 '15 at 17:18
2
\$\begingroup\$

Matlab, 100 90 bytes

Not as small as I'd like - especially the conversion from boolean to the strings is very long. I tried to shave off a few bytes by switching to Octave, but apparently %c is not supported for textscan yet in Octave.

B=textscan(G,'%f,%f,%c%s\n');xor(B{1}>=B{2},B{3}==85);C(a)={'STOP'};C(~a)={'WAIT'};char(C)

Personally I think it is nice that this solution is the only one so far that does not use split :)

EDIT: originally solved the equals situation way too complex.

\$\endgroup\$
  • \$\begingroup\$ This is actually 92 bytes - you missed the a= bit before the xor function call. Though even then it doesn't actually produce the correct output. \$\endgroup\$ – Tom Carpenter Nov 29 '15 at 1:25
2
\$\begingroup\$

Javascript ECMAScript 6, 112b

var O="";for(let E of G.split("\n"))[A,B,C]=E.split(","),O+=("U"<C||-1)*(A-B)>0?"STOP\n":"WAIT\n";console.log(O)

Only on ECMAScript 6 compatible browsers

Explanation

("U"<C||-1)*(A-B)>0?"STOP\n":"WAIT\n"

It makes use of the fact that if we ask if 0 is true it will return false, so we can say 1 for UP, -1 for DOWN. Then we multiply that by the difference of current price and optimal price to make both of them work for the greater than 0 part

If condition is met, return STOP, otherwise (including equal values) return WAIT

Needs further golfing

\$\endgroup\$
2
\$\begingroup\$

Javascript (ES6), 82 80 79 bytes

Edit: -2 using @JuanCortés multiplication method

Edit: -1 using a trick to reduce the multiplication method

alert(G.replace(/(.+),(.+),(.)+/g,(x,c,o,t)=>(c-o)*~{P:-2}[t]>0?'STOP':'WAIT'))

Commented:

alert(                           // alert final output after replacement
    G.replace(/(.+),(.+),(.)+/g, // capture group for sections of each line
                                 // (.)+ captures only the last character
                                 // . doesn't match newlines, so this runs for each line
        (x,c,o,t)=>              // use a function to calculate each replacement string
            (c - o)              // calculate difference, negative for o>c
            *                    // multiply by
            ~{ P: -2 }[t]        // { P: -2 }[t] returns -2 for UP ('P') -2, else undefined
                                 // ~-2 => 1, ~undefined => -1
            > 0                  // if result > 0 (muplication of negatives or positives)
            ? 'STOP' : 'WAIT'    // return corresponding replacement string
    )
)

Snippet Demo:

function run(){
    G = input.value;
    /* start solution */
    alert(G.replace(/(.+),(.+),(.)+/g,(x,c,o,t)=>(c-o)*~{P:-2}[t]>0?'STOP':'WAIT'))
    /* end solution */
}
<textarea id="input" cols="25" rows="7">80,90,UP
150,100,DOWN
65,65,UP
1618,1618,DOWN
840,1200,DOWN
54,12,UP
30,1,UP</textarea><br />
<button id="run" onclick="run();">Run</button>

Revision History:

// 80
alert(G.replace(/(.+),(.+),(.)+/g,(x,c,o,t)=>(c-o)*(t>'N'||-1)>0?'STOP':'WAIT'))

// 82
alert(G.replace(/(.+),(.+),(.)+/g,(x,c,o,t)=>+c>o&t>'N'|+c<o&t<'P'?'STOP':'WAIT'))
\$\endgroup\$
  • \$\begingroup\$ Care to explain the logic? Looks awesome but I have no idea whats going on \$\endgroup\$ – Juan Cortés May 19 '15 at 16:31
  • \$\begingroup\$ @JuanCortés I've added a commented version :) \$\endgroup\$ – nderscore May 19 '15 at 16:37
  • \$\begingroup\$ Cheers! That I do understand \$\endgroup\$ – Juan Cortés May 19 '15 at 16:59
2
\$\begingroup\$

C- 91 Bytes

Because C has to be there somewhere

Now looks very similar to @nutki version although working out whether to output "STOP" or "WAIT" is diffferent.

Ungolfed-

main(i,j)
{
    char c[5];
    while(scanf("%i,%i,%s",&i,&j,c)+1)
        puts((j-i)*(*c-70)<0?"STOP":"WAIT");
}

Golfed-

 main(i,j){char c[5];while(scanf("%i,%i,%s",&i,&j,c)+1)puts((j-i)*(*c-70)<0?"STOP":"WAIT");}

The old one

Ungolfed-

int main()
{
    int i,j;
    char *c="";
    while(scanf("%i,%i,%s",&i,&j,c)+1)
    {
        if(i<j)
        {
            if(*c-68)
                printf("WAIT\n");
            else
                printf("STOP\n");
        }
        if(i>j)
        {
            if(*c-68)
                printf("STOP\n");
            else
                printf("WAIT\n");
        }
        if(i==j)
            printf("WAIT\n");
    }
    return 0;
}

Golfed

#define W printf("WAIT\n");
#define S printf("STOP\n");
int main(){int i,j;char *c="";while(scanf("%i,%i,%s",&i,&j,c)+1){if(i<j){if(*c-68)W else S}if(i>j){if(*c-68)S else W}if(i==j)W}return 0;}

I'll continue to try to cut it down

\$\endgroup\$
  • \$\begingroup\$ This code will just crash. You need char c[4] instead of char *c="" (which is also shorter). \$\endgroup\$ – nutki May 20 '15 at 6:46
  • \$\begingroup\$ @nutki , Actually, its just Undefined Behavior. A crash need not happen. \$\endgroup\$ – Spikatrix May 20 '15 at 8:56
  • \$\begingroup\$ @CoolGuy, writing 5 bytes to a read only location of 1 byte. Is there a system in which this will not segfault? \$\endgroup\$ – nutki May 20 '15 at 10:32
  • \$\begingroup\$ @nutki - obviously my Windows PC as it worked on that! \$\endgroup\$ – euanjt May 20 '15 at 10:36
  • \$\begingroup\$ @nutki , See? TheE's system did not throw a segfault. It is just undefined behavior. Might work on one system, but won't on the other. Anything can happen. But who cares? This is code golf so the program just needs to "work" :) BTW, shouldn't it be char c[5] ( 1 space for the \0 at the end )? \$\endgroup\$ – Spikatrix May 20 '15 at 10:40
1
\$\begingroup\$

Python 3 - 108 106 102 97B

for l in G:a,b,c=l.split(',');s=int(a)-int(b);d=c<'E';print(['WAIT','STOP'][(s<0)*d+(s>0)*(1-d)])

Work in progress...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.