Fast, Cheap, and Good - Choose any Two

43

4

As programmers, we all know the saying: "You can have it fast and good, but it won't be cheap, you can have it cheap and good, but it won't be fast, or you can have it fast and cheap, but it won't be good."

For this challenge, you are implementing an imaginary configuration tool for your custom programming services. You should render a set of three check boxes, with a heading of "SELECT ANY TWO":

SELECT ANY TWO  
☐ FAST  
☐ CHEAP  
☐ GOOD

Once two items have been selected, the third item must be disabled. Upon deselecting one of the two selected items, all options must again be enabled. Put another way, if zero or one items are selected, all are still enabled, but if two items are selected, the third must be disabled.

No special controls allowed. The check boxes should be the standard check box in your language of choice. For example, don't use a "CheckBoxList" control, if your language has one. I'm imagining most entries will be HTML/jQuery, but that is not a rule. This is code golf, looking for the shortest entry.

WINNERS SO FAR

I'll break it down into categories. There are some clear winners:

jQuery: nderscore, Mr. Tenacity Under 100b when you exclude text "resources". Honorable mention should also go to Matt for introducing the jQuery concepts that many took inspiration from.

Dyalog APL: marinus, a.k.a. Mr. Unicode How do you type all those things? I can see why you would want to write short programs.

PHP: SuperScript I believe this is the shortest entry that actually disables rather than deselecting the third option, following the strictest interpretation of the rules.

Bruce Pierson

Posted 2014-05-08T02:09:30.690

Reputation: 533

Can I just make it so that only two can be selected at a time? So that selecting the third de-selects one of the other ones? Or perhaps add an accept button that gets greyed out if 3 options are selected? – Justin – 2014-05-08T03:30:45.920

7@Quincunx - Since there is no heuristic (outside of mind-reading) that could decide which one to deselect, this would confuse the user... so I'll have to say no, because we don't want the first impression of our custom software services to be a bad one. ;) – Bruce Pierson – 2014-05-08T03:53:49.763

This question interested me in Python 3's tkinter, so I am trying to learn that now. IMO, the best way to learn GUI is by trial and error. I tried this: http://ideone.com/YHLZIQ . Result: rapid opening of new GUIs. I had to open task manager to close them. :-). Image (the number soon climbed to 340: http://i.stack.imgur.com/c9wQi.png)

– Justin – 2014-05-08T05:29:48.180

The bonus contest should be another question as there is no objective primary winning criterion or any description of the "bonus". It said that code should be "...elegant and flexible..." and "...concise and clear..." which is against [tag:code-golf]. VTC as unclear what you are asking. Please don't radically change questions long after they are asked. – user80551 – 2014-05-08T17:38:02.837

Fair enough, removed. – Bruce Pierson – 2014-05-08T17:42:03.603

1@BrucePierson Actually, there is. We could deselect the oldest selected checkbox. However, the code for that would be much more than the code you require. – Justin – 2014-05-08T20:15:05.947

@Quincunx Well, no question that your suggestion fits the precise definition of "heuristic" - certain parts of the definition, anyway. :) – Bruce Pierson – 2014-05-08T20:40:37.857

Is it permitted to prevent the user from checking the 3rd checkbox instead of actually disabling it? – nderscore – 2014-05-08T23:20:54.087

@nderscore yes.

– Justin – 2014-05-09T01:09:17.657

What do you mean by "Don't use a check box list"? If you applied this too strictly, one wouldn't even be allowed to use jQuery. – Bergi – 2014-05-09T13:50:12.937

"Do not use these controls for SQLite." – Michael – 2014-05-09T15:43:05.813

I've been having a discussion on meta, are the requirements for this challenge to write a function or a fully functional program? http://meta.codegolf.stackexchange.com/q/1550

– iamkrillin – 2014-05-10T13:25:32.903

@iamkrillin I think all the entries so far are executable in their context. Obviously a framework of some kind is usually present (browser, Qt, etc.). But it must display the page/form and allow interaction. – Bruce Pierson – 2014-05-10T16:22:22.633

If something is good and cheap, it won't be fast. Therefore it won't be cheap either. – bjb568 – 2014-05-11T20:52:10.627

<anal>"Pick two" sounds much better than "Select any two" – o0'. – 2014-05-12T11:00:36.287

Would we be allowed to simply have SELECT ANY TWO be the title of the window, rather than a label inside? – Justin – 2014-11-03T08:18:04.263

Answers

23

Javascript (ES5) with jQuery - 143 (Demo)

I modified Matt's solution and golfed it as far down as I think it can go:

$("*").html(["SELECT ANY TWO","FAST","GOOD","CHEAP"].join("<input type=checkbox onclick=(a=$('input:not(:checked)')).prop('disabled',!a[1])>"))

Javascript (ES5) without jQuery - 185 175 (Demo)

Using jQuery is kind of cheating, so here's a solution without it:

(d=document).write(["SELECT ANY TWO","FAST","GOOD","CHEAP"].join("<input type=checkbox onclick='for(b in a=d.querySelectorAll(\"input:not(:checked)\"))a[b].disabled=!a[1]'>"))

If we're allowed to prevent the user from checking the 3rd box instead of actually disabling the field, we can make it even shorter:

With jQuery - 126 123 (Demo)

$("*").html(["SELECT ANY TWO","FAST","GOOD","CHEAP"].join("<input type=checkbox onclick=this.checked*=!$(':checked')[2]>"))

Without jQuery - 150 147 (Demo)

(d=document).write(["SELECT ANY TWO","FAST","GOOD","CHEAP"].join("<input type=checkbox onclick=this.checked*=!d.querySelectorAll(':checked')[2]>"))

nderscore

Posted 2014-05-08T02:09:30.690

Reputation: 4 912

Cool. Using .join is a good trick! – Robbie Wxyz – 2014-05-08T19:16:04.120

1"SELECT ANY TWO0FAST0GOOD0CHEAP".replace(/0/g, is another way to do it resulting in the same length. – nderscore – 2014-05-08T19:17:30.530

just being picky, the jquery version should use prop, not attr – Einacio – 2014-05-08T19:21:18.940

@Einacio your wish is my command! – nderscore – 2014-05-08T19:22:34.603

(Y) if it is with the same char lenght, why not promote good practices, right? – Einacio – 2014-05-08T19:23:55.690

Nice work. Agreed on the .join, great approach. – Matt – 2014-05-08T23:20:15.890

5@Einacio But codegolf is about worst practices! :P – nderscore – 2014-05-09T00:07:56.020

@nderscore is officially at 99b with jQuery once you take out the required text "resources". That is going to be tough to top! – Bruce Pierson – 2014-05-09T03:17:54.063

The second solution doesn't work if you use the keyboard to check the checkbox, does it? – John Dvorak – 2014-05-31T13:16:45.743

@JanDvorak pressing spacebar while the checkbox is in focus does trigger a click event, so it works. – nderscore – 2014-05-31T15:10:14.107

29

JavaScript - 184 169 (with jQuery)

b="input",a="<input type=checkbox>",c=":checked";$("body").html("SELECT ANY TWO"+a+"FAST"+a+"GOOD"+a+"CHEAP").click(function(){$(b).not(c).attr("disabled",!!$(b+c)[1])})

http://jsfiddle.net/L33JK/16/

EDIT: improved with help from @Daniel Lisik - https://codegolf.stackexchange.com/a/26805/16278

Matt

Posted 2014-05-08T02:09:30.690

Reputation: 777

5Nice! Not enough rep to upvote... but you're hired! – Bruce Pierson – 2014-05-08T03:55:57.717

2The more I look at this, the more I'm learning. The cleverness of the variable assignment inside a jQuery selector. Very cool. Also, could you explain what the "double bang" (!!) is doing? – Bruce Pierson – 2014-05-08T05:01:11.020

1The single bang, coerces a boolean value, and double will obviously invert that. undefined coerces to true. That and the variable assignment are probably the only little tricks used really. – Matt – 2014-05-08T05:03:55.260

Your code can be reduced to 179 characters like this: a="<input type='checkbox'>",b="input",c=":checked",$("body").html("SELECT ANY TWO"+a+"FAST"+a+"GOOD"+a+"CHEAP").change(function(){$(b+":not("+c+")").attr("disabled",!!$(b+c)[1])}) http://jsfiddle.net/L33JK/15/

– display-name-is-missing – 2014-05-08T14:10:06.777

Even less in the comment I left on yours, 169! – Matt – 2014-05-08T14:12:56.177

if you're defining b=input, can't you make a = "<"+b+" type=checkbox>"? – Not that Charles – 2014-05-08T15:47:22.107

@Charles you can, but there won't be any difference in character length, (#+b+" is 5 characters and so is input). – display-name-is-missing – 2014-05-08T16:29:42.167

Hey, nice solution! You can save two more bytes using !!$(c)[1] as :checked should only apply the <input>s anyway! – Dom Hastings – 2014-05-08T16:43:23.183

1

143: http://jsfiddle.net/_nderscore/69Ted/

– nderscore – 2014-05-08T17:18:37.513

since the inputs are the only elements, you can set b='*' and it'll work the same – Einacio – 2014-05-08T17:33:46.720

@Einacio the body tag will be captured by * as well – nderscore – 2014-05-08T17:34:58.113

@nderscore so? that only means the body will be set a disabled attribute that doesn't affect it. also, only !!$(c)[1] is needed, since :checked only filters the checkbox. speed is not important here – Einacio – 2014-05-08T17:41:52.973

It only matters in my 143 solution above. Nevermind :) – nderscore – 2014-05-08T17:56:39.667

12

Dyalog APL (on Windows) (169)

This is a static function, to test it if you don't know APL, type )ed C and paste this in the edit window, then run C.

C
'R'⎕WC'Form' 'Select any two',2/⊂S←2/20
1 21 41{('R.',⊃⍵)⎕WC'Button'⍵(⍺1)S'Check'('Event' 'Select' 'F')}¨'Fast' 'Cheap' 'Good'
B←R.(F C G)
F←{B.Active←X∨2≠+/X←B.State}

Newer bits of APL have long keywords. I still beat HTML though.

Explanation:

  • 'R'⎕WC'Form' 'Select any two',2/⊂S←2/20: create a form R, with title Select any two and size and position 20 20. Also stores 20 20 in S.
  • 1 21 41{...}¨'Fast' 'Cheap' 'Good': for each of these pairs of data (name and y-coordinate, which are the only variables that differ between the checkboxes:
    • ('R.',⊃⍵)⎕WC'Button': create a button within R with the first letter of the name,
    • ⍵(⍺1)S'Check': with the right argument as the title, (left arg, 1) as position, reusing S as the size and Check as style,
    • ('Event' 'Select' 'F'), which calls the function F when clicked.
  • B←R.(F C G): use B as an abbreviation for the three checkboxes we created
  • F←{...}: define the callback function as:
    • X←B.State: get the state for each checkbox and store them in X,
    • X∨2≠+/X: sum X, if this is not equal to two all checkboxes must be active, if it is equal to two only checked checkboxes must be active
    • B.Active←: enable or disable the checkboxes

Result:

screenshot

marinus

Posted 2014-05-08T02:09:30.690

Reputation: 30 224

Great explanation, thanks! – Bruce Pierson – 2014-05-08T14:45:18.663

11

Python 3 2, 454 434 ... 393 392 bytes

I thought, Python must be shorter than Java. Here is the "proof" (EDIT: now it really is shorter):

from Tkinter import*
t=Tk()
r=str.replace
exec r(r(r(r('a@b@c@l=Label(t,text="SELECT ANY TWO");A`FAST|a);B`CHEAP|b);C`GOOD|c);l^A^B^C^','`','=Checkbutton(t,text="'),'|','",v='),'^','.pack();'),'@','=IntVar();')
def f(p,b,B,s):
 for i in 0,1,2:
    y=b[i].get()
    if p[i]-y:
     p[i]=y;s-=1
     if p[i]:s>0and B[i].toggle();s+=2
 t.after(1,f,p,b,B,s)
t.after(1,f,[0]*3,[a,b,c],[A,B,C],0)
t.mainloop()

For those of you curious as to what the exec expression actually executes, it executes this (this is what the replaces do to the string. Newlines added for readability):

a=IntVar();
b=IntVar();
c=IntVar();
l=Label(t,text="SELECT ANY TWO");
A=Checkbutton(t,text="FAST",v=a);
B=Checkbutton(t,text="CHEAP",v=b);
C=Checkbutton(t,text="GOOD",v=c);
l.pack();
A.pack();
B.pack();
C.pack();

This uses the same logic as my Java answer: unselect the checkbox if it causes more than 2 checkboxes to be selected. Unf Fortunately Unfortunately, I spent more less more bytes doing this.

enter image description here

EDITS:

  1. massive adjustment of code to use exec, saving a whopping 1 byte!
  2. switched to python 2 to squeeze two bytes from the exec (removing parentheses).
  3. more golfing. Includes changing range(3) to 0,1,2 and changing the indentation to have one layer of tabs. Unsure if \t\t would work instead of \t__(_ is the space character). Finally reached the longest my Java answer ever was.
  4. used replace trick
  5. used Bakiru's suggestion, and golfed some more. Actually made it shorter than Java! But now, the Java answer got golfed more, so this is again longer. :-(
  6. used improved replace trick.
  7. changed a != for a -.

Justin

Posted 2014-05-08T02:09:30.690

Reputation: 19 757

Interesting approach. +1 – cjfaure – 2014-05-08T17:07:19.037

I can cheat with the turbo mode on my keyboard. First, I check two boxes. Second, I use Tab to highlight the third. Now I hold Space Bar in turbo mode for a few seconds. Sometimes, this checks the third box! – kernigh – 2014-05-08T23:12:00.633

@kernigh I believe that is because my code gets to the point where it knows that the box has been toggled, but the code hasn't reached the point where it re-toggles the box. So if you toggle the box in that time (to off), my code will put a checkmark on it. – Justin – 2014-05-09T03:34:40.250

1You can avoid the indented block starting with if p[i] using an and instead of an if: if p[i]:s>1 and B[i].toggle();s+=1. – Bakuriu – 2014-05-09T07:36:10.577

@kernigh I was wrong; replacing B[i].toggle() with B[i].deselect() doesn't change anything. I have no idea why this is so. Perhaps it is a flaw with tkinter – Justin – 2014-05-09T23:57:39.780

10

Java, 421 ... 369 351 bytes

import java.awt.*;class F extends Checkbox{F(String s){super(s);}public static void main(String[]a){new Frame(){{add(new Panel(){{add(new Label("SELECT ANY TWO"));F[]c={new F("FAST"),new F("CHEAP"),new F("GOOD")};for(F b:c){add(b);b.addItemListener(e->{int x=0;for(F d:c)x+=d.getState()?1:0;if(x>2)((F)e.getSource()).setState(1<0);});}}});}}.show();}}

Java... because Java. Nicer looking code:

import java.awt.*;

class F extends Checkbox {
    F(String s) {
        super(s);
    }

    public static void main(String[] a) {
        new Frame() {
            {
                add(new Panel() {
                    {
                        add(new Label("SELECT ANY TWO"));
                        F[] c = {new F("FAST"), new F("CHEAP"), new F("GOOD")};
                        for (F b: c) {
                            add(b);
                            b.addItemListener(e -> {
                                int x = 0;
                                for (F d: c) {
                                    x += d.getState() ? 1 : 0;
                                }
                                if (x > 2) ((F) e.getSource()).setState(1 < 0);
                            });
                        }
                    }
                });
            }
        }.show();
    }
}

Sample run (different sizings of the window, first is on startup):

enter image description here
enter image description here
enter image description here

The checkboxes are arranged horizontally; this is allowed. It would take much more to align it properly. Also, I'm disabling by unchecking the box when it is clicked, not by making it impossible to be clicked.

EDITS:

  1. saved 3 bytes by making the main class extend Checkbox.
  2. reread Lambda Expressions and realized that the type name was unnecessary. Take that Python!
  3. converted a while loop to a foreach loop (thanks Lee); why didn't I think of that before?
  4. saved 18 bytes by using an anonymous class and an instance initalizer for both the Frame and Panel.

Justin

Posted 2014-05-08T02:09:30.690

Reputation: 19 757

No restriction on the alignment (so I suppose Matt could reduce his by 5 characters). Props for a complete running program... but I don't see that the third option is disabled. – Bruce Pierson – 2014-05-08T04:15:29.130

@BrucePierson It is disabled. It cannot be clicked. If it is clicked, nothing happens. – Justin – 2014-05-08T04:16:45.323

2Ah, I think I see. You're immediately "unsetting" the checked state without disabling? That would be acceptable. – Bruce Pierson – 2014-05-08T04:19:20.013

@BrucePierson That's right. To actually disable, I'd have to change if(x>2)((Checkbox)e.getSource()).setState(1<0); to if(x>2){Checkbox b=(Checkbox)e.getSource();b.setState(1<0);b.setEnabled(1<0);} – Justin – 2014-05-08T04:22:48.577

That works. Thanks for the edit on the OP, by the way - looks much better. :) – Bruce Pierson – 2014-05-08T04:30:08.677

1

@BrucePierson Whenever you think, This looks funny when it has to do with using a character representation of some graphical thing, look for unicode. Alternatively, for graphical design things, turn to User Experience SE: http://i.stack.imgur.com/xFkzy.png

– Justin – 2014-05-08T04:39:50.000

You can save 4 bytes by getting rid of the spaces around the equals signs for variables f and p. – corsiKa – 2014-05-08T15:28:41.330

@corsiKa Thanks. I usually miss some stuff like that when I shrink my code. I need to write an auto-golfer (preferably a regular expression that I can run in Netbeans with replace) that does that for me. – Justin – 2014-05-08T19:12:55.413

You could replace the while(i<3){x+=c[i++].getState()?1:0;} with for(F d:c){x+=d.getState()?1:0;} which would save a few characters. – Opal – 2014-05-11T00:33:16.740

I'd do Arrays.stream(new F("FAST"), new F("CHEAP"), new F("GOOD")).foreach(/*stuff*/) to save some more code. – Simon Kuang – 2014-05-11T06:38:35.290

Why 1<0 and not just false? – Simon Kuang – 2014-05-11T06:39:53.670

@SimonKuang 1<0 is 3 chars. false is 5. And your other suggestion is longer. – Justin – 2014-05-11T06:47:01.680

Sadly, if(java.util.Arrays.stream(c).allMatch(F::getState)) is longer than int x=0;for(F d:c)x+=d.getState()?1:0;if(x>2) – Justin – 2014-11-03T08:39:52.337

10

Rebol, 219 197

load-gui p: func[p][p/state/value]x: func[v][if all[p a p b p c][set-face v false]] view [title"SELECT ANY TWO"a: check"FAST"on-action[x a]b: check"CHEAP"on-action[x b]c: check"GOOD"on-action[x c]]

Ungolfed:

load-gui    ;; this is temporary while r3-gui is in beta

p: func [p] [p/state/value]

x: func [v] [
    if all [p a p b p c] [set-face v false]
]

view [
    title "SELECT ANY TWO"
    a: check "FAST" on-action [x a]
    b: check "CHEAP" on-action [x b]
    c: check "GOOD" on-action [x c]
]

This is the Rebol 3 View dialect (r3-gui). Screendump below from Ubuntu Linux:

example of rebol 3 view

Update - Thanks to Earl & Graham from Rebol SO Chatroom for shaving 22 chars of the code - http://chat.stackoverflow.com/transcript/message/16345039#16345039

draegtun

Posted 2014-05-08T02:09:30.690

Reputation: 1 592

It is invalid answer, as third is disabled but also checked, that means all 3 are checked, so please fix it. – ST3 – 2014-05-09T06:40:12.477

2@ST3 - You are incorrect I'm afraid. The "GOOD" checkbox isn't checked or in fact disabled (my code simply flicks the third box checked OFF). This is how Rebol 3 view shows an unchecked box (by default). – draegtun – 2014-05-09T07:01:25.480

1

@ST3 et al - Here is a link showing default checkbox look I've described above (1st image shows no checkboxes clicked, 2nd just "GOOD") - https://plus.google.com/u/0/104216037702741908932/posts/Z2EbuQX67aq

– draegtun – 2014-05-09T07:11:14.650

Well... I look into print-screen you added and I see all three checkboxes checked, just only one cannot be unchecked. – ST3 – 2014-05-09T07:14:35.990

3@ST3 - A greyed out checkbox is just Rebol 3 View way of showing that it's a checkbox that can be checked. The tick turns green when checked and turns back to grey when unchecked. These are the defaults. In the image in answer above you can see that "GOOD" as the input focus (blue blur) because its being "clicked" but it remains grey and not green (so not checked). – draegtun – 2014-05-09T07:18:45.843

7

C++11/Qt5.2 - 561 481 433 423 369

Because why not.

Shockingly, as of now we are shorter than Python, and the non-buggy C#, and tied with Java!

Credits to EveBird for cutting it down from 561 to 481.

And once more EveBird shortens it from 481 to 433!

Took a few off with a lambda connect

Down to 389 with C++11 initializers

And 373 without the separate class

Removed a few spaces - 369

Golf'd:

#include<QtWidgets>
#define C(x,y,z)z.setEnabled(x.isChecked()+y.isChecked()<2);
#define S(x)l.addWidget(&x);
#define X(x)S(x);x.connect(&x,&QCheckBox::clicked,[&](){C(g,f,c)C(g,c,f)C(f,c,g)});
int main(int n,char**v){QApplication a(n,v);QWidget m;QLabel t{"Select any two"};QCheckBox g{"Good"},f{"Fast"},c{"Cheap"};QVBoxLayout l(&m);S(t)X(g)X(f)X(c)m.show();a.exec();}

Sort of Un-Golfed:

#include<QtWidgets>

#define C(x,y,z)z.setEnabled(x.isChecked()+y.isChecked()<2);
#define S(x)l.addWidget(&x);
#define X(x)S(x);connect(&x, &QCheckBox::clicked, [&](){C(g,f,c)C(g,c,f)C(f,c,g)});

int main(int n,char**v){ 
    QApplication a(n,v);
    QWidget m;
    QLabel t{"Select any two"};
    QCheckBox g{"Good"},f{"Fast"},c{"Cheap"};
    QVBoxLayout l(&m);
    S(t)X(g)X(f)X(c)m.show();
    a.exec();
}

GFC

Jacob Hacker

Posted 2014-05-08T02:09:30.690

Reputation: 171

Can improve a bit more: replace QWidget m with QDialog m and m.show();a.exec() with m.exec(). – Toby Speight – 2015-10-19T15:24:06.620

1+1 for the self-flagellating "why not" :) – Bruce Pierson – 2014-05-10T04:58:08.130

6

CoffeeScript - 167, 154

CoffeeScript port of @Matt's answer.

b="input";a="<input type=checkbox>";c=":checked";$("body").html("SELECT ANY TWO#{a}FAST#{a}GOOD#{a}CHEAP").click ->$(b).not(c).attr "disabled",!!$(b+c)[1]

Somewhat ungolfed:

b = "input"
a = "<input type=checkbox>"
c = ":checked"

$( "body" ).html( "SELECT ANY TWO#{a}FAST#{a}GOOD#{a}CHEAP" ).click ->
    $( b ).not( c ).attr "disabled", !!$( b + c )[1]

JSFiddle.

Tony Ellis

Posted 2014-05-08T02:09:30.690

Reputation: 1 706

5

Thanks to Rotem and Johnbot for the golfing help!

C# 343 334

This one uses the same "cheat" as Quincunx's Java answer - the checkboxes aren't actually disabled; they just don't allow you to check them if that check makes 3.

using System.Windows.Forms;using System.Linq;class P:Form{static void Main(){P p=new P();p.Text="SELECT ANY TWO";int y=0;var a=new CheckBox[3];foreach(var n in "FAST CHEAP GOOD".Split()){var c=new CheckBox();a[y]=c;c.Top=y++*50;c.Text=n;c.Validating+=(s,e)=>{if(a.Count(b=>b.Checked)>1)e.Cancel=true;};p.Controls.Add(c);}Application.Run(p);}}

There's also a minor bug that you can't close the window after selecting the third checkbox unless you unselect one, because the validation won't pass. But this is , so who cares? ;)

C# 403 397 374

This is a proper one that actually disables the third checkbox.

using System.Windows.Forms;using System.Linq;class P:CheckBox{static void Main(){var p=new Form{Text="SELECT ANY TWO"};P[]a=null;a="FAST CHEAP GOOD".Split().Select((x,i)=>{var c=new P{Top=i*50,Text=x};c.Click+=(s,e)=>{a.First(b=>!b.Checked).Enabled=a.Count(b=>b.Checked)>1?1<0:a.All(b=>b.Enabled=0<1);};p.Controls.Add(c);return c;}).ToArray();Application.Run(p);}}

Screenshot

Kinda ungolfed:

using System.Windows.Forms;
using System.Linq;

class P:Form
{
    static void Main()
    {
        P p = new P();
        p.Text = "SELECT ANY TWO";
        int y = 0;
        var a = new CheckBox[3];
        foreach (var n in "FAST CHEAP GOOD".Split())
        {
            var c = new CheckBox(); a[y] = c; c.Top = y++ * 50; c.Text = n; c.Click += (s, e) =>
            {
                if (a.Count(b => b.Checked) == 2)
                {
                    a.First(b => !b.Checked).Enabled = false;
                }
                else
                {
                    foreach (var b in a) b.Enabled = true;
                }
            };
            p.Controls.Add(c);
        }
        Application.Run(p);
    }
}

Bob

Posted 2014-05-08T02:09:30.690

Reputation: 844

1Couldn't if(a.Count(b=>b.Checked)==2)e.Cancel=true; be rewritten as e.Cancel=a.Count(b=>b.Checked)==2;? – Rotem – 2014-05-08T11:16:37.373

@Rotem Yes, yes it could. I'm dumb. And there's a similar optimisation for the other one. Thanks! – Bob – 2014-05-08T14:32:25.913

Wait, no, there isn't for the other one. Eh, still saved some chars. – Bob – 2014-05-08T14:40:32.327

1If you switch the inheritance to CheckBox, use object initializers and abuse Linq a bit you can get the proper one down to 374: using System.Windows.Forms;using System.Linq;class P:CheckBox{static void Main(){var p=new Form{Text="SELECT ANY TWO"};P[]a=null;a="FAST CHEAP GOOD".Split().Select((x,i)=>{var c=new P{Top=i*50,Text=x};c.Click+=(s,e)=>{if(a.Count(b=>b.Checked)>1){a.First(b=>!b.Checked).Enabled=1<0;}else a.All(b=>b.Enabled=0<1);};p.Controls.Add(c);return c;}).ToArray();Application.Run(p);}} – Johnbot – 2014-05-09T11:25:33.563

@Johnbot Thanks! Never would have thought of most of that. Heck, I forgot object initialisers existed! – Bob – 2014-05-09T11:48:18.883

1364 if you use the conditional operator in place of the if statement. Replace if(a.Count(b=>b.Checked)>1){a.First(b=>!b.Ch‌​ecked).Enabled=1<0;}else a.All(b=>b.Enabled=0<1); with a.First(b=>!b.Checked).Enabled=a.Count(b=>b.Checked)>1?1<0:a.All(b=>b.Enabled=0<1); – Johnbot – 2014-05-09T12:08:54.177

5

PHP, Javascript, jQuery - 135b

I was admiring @nderscore's answer, but then I decided to copy and one-up him.

<?echo"SELECT ANY TWO".($m="<input type=checkbox onclick=(a=$('input:not(:checked)')).prop('disabled',!a[1])>")."FAST$m GOOD$m CHEAP"?>

Basically I replaced his .join trick with some PHP Hypertext Preprocessing.

Robbie Wxyz

Posted 2014-05-08T02:09:30.690

Reputation: 393

When you consider that 27 bytes are required for the text "resources" in the program, this is getting very close to a 100b program. Well done! – Bruce Pierson – 2014-05-08T21:07:52.017

1I'm not much of a PHP golfer, but I chopped a few bytes off for you: (128) SELECT ANY TWO<?=($m="<input type=checkbox onclick=(a=$('input:not(:checked)')).prop('disabled',!a[1])>").FAST.$m.GOOD.$m.CHEAP; – nderscore – 2014-05-08T23:05:57.880

5

Ruby, 219 218 bytes

I use the same Tk widgets as the Python 3 answer by Quincunx.

This program breaks the rules because it has a check box list. (The rules said, "Don't use a check box list.") Yes, a is an array of 3 TkCheckButton objects, and I believe that an array is a list. My defense is that I did not use any existing check box list, but I used the standard check boxes and made my own list.

require'tk'
o=->(c){c.variable.value>?0}
TkLabel.new{text'SELECT ANY TWO'
pack}
a=%w[FAST CHEAP GOOD].map{|t|TkCheckButton.new{text t
command{a.map{|c|c.state a.count(&o)<2||o[c]?:normal: :disabled}}
pack}}
Tk.mainloop

CHEAP and GOOD checked, but FAST disabled

I tested with Ruby 2.1.0 and Tk 8.5.15.

  • o[c] is a predicate to test if check button c is selected. With the default strings, c.variable.value is '0' or '1', so the string comparison is only true if '1'>'0'. EDIT: I saved 1 byte (219 down to 218) by changing '0' to ?0. In Ruby, ?0 is a character constant.
  • a.count(&o) uses the predicate to count the selected check buttons.
  • When the user toggles a check button, the command calls a.map to loop for all buttons, making them :normal or :disabled.

kernigh

Posted 2014-05-08T02:09:30.690

Reputation: 2 615

1Very good. No rule breaking here - I was referring to a check box list control that may happen to be part of the language framework. I believe all of the answers so far use some kind of map or selector, so this is totally legit. – Bruce Pierson – 2014-05-08T21:01:35.917

5

AngularJS - 214

<input type=checkbox ng-model=fast ng-disabled=cheap&&good>FAST</input>
<input type=checkbox ng-model=cheap ng-disabled=fast&&good>CHEAP</input>
<input type=checkbox ng-model=good ng-disabled=fast&&cheap>GOOD</input>

user12345

Posted 2014-05-08T02:09:30.690

Reputation: 161

I tried this out at JSFiddle, but without any success. Can you provide a working example?

– r3mainer – 2014-05-09T09:42:00.930

http://plnkr.co/edit/Y1FQOQyGJXlC9r3Rk2Zr?p=preview – user12345 – 2014-05-09T10:24:17.950

You did not mention "ng-app". Check <head> in my example. – user12345 – 2014-05-09T10:25:34.867

1

Ah, OK :-) You can golf it down a bit by removing the quotation marks and extra line breaks.

– r3mainer – 2014-05-09T10:33:22.983

4

Mathematica

A more code-golfed version as suggested by David, 255 characters:

h = Checkbox;
i = Dynamic;
j = Enabled;
t = True;
i[
 If[Total@Boole@{a, b, c} == 2,
  {d, e, f} = {a, b, c},
  {d, e, f} = {t, t, t}
  ];
 Row@{
   "SELECT ANY TWO",
   h[i@a, j -> d], "FAST",
   h[i@b, j -> e], "CHEAP",
   h[i@c, j -> f], "GOOD"
   }
 ]

user11030

Posted 2014-05-08T02:09:30.690

Reputation:

You can save some characters by using h=Checkbox;i=Dynamic;j=Enabled. – DavidC – 2014-05-08T12:42:59.003

@DavidCarraher Thanks, I can see myself using that technique for other code golfing question in the future as well. – None – 2014-05-08T12:49:54.037

1No need to include both versions. And don't forget to use h and to adjust your char count in the heading. – DavidC – 2014-05-08T23:34:53.420

4

JavaScript (with jQuery) - 224, 222, 210, 205, 178

a="<input type=checkbox>",c=":checked",e="input",f="disabled",d=$("body").html("SELECT ANY TWO"+a+" FAST"+a+"CHEAP"+a+"GOOD").click(function(){$(e).not(c).attr(f,$(e+c).length>1)})

Thanks to a comment from brilliant @Matt I reduced the code by 27 characters.

JSFiddle

display-name-is-missing

Posted 2014-05-08T02:09:30.690

Reputation: 271

Save 25 or so by moving your condition $(e+c).length>1 into the assignment as such: $(e).not(c).attr(f,$(e+c).length>1) since you're only changing the boolean itself. – Matt – 2014-05-08T13:47:51.383

1Managed to get it down to 169 using a mix of yours and mine. The !! coercion and a little extra golfing with not assigning body to d. a="<input type=checkbox>",c=":checked",e="input";$("body").html("SELECT ANY TWO"+a+"FAST"+a+"CHEAP"+a+"GOOD").click(function(){$(e).not(c).attr("disabled",!!$(e+c)[1])}) – Matt – 2014-05-08T14:11:52.617

4

mIRC script (727 719 bytes)

Forgot about this language until a drunken conversation last night.

alias select_two {
  dialog -m s2 s2
}

dialog s2 {
  title "Select any two:"
  size -1 -1 200 100
  check "Fast",1, 5 10 170 25
  check "Cheap",2, 5 30 170 25
  check "Good",3, 5 50 170 25 
}

on *:dialog:s2:sclick:*: {
  if ($did(s2, $did).state = 1) {
    if ($did = 1) {
      if ($did(s2, 2).state = 1) { did -b s2 3 }
      if ($did(s2, 3).state = 1) { did -b s2 2 }
    }
    if ($did = 2) {
      if ($did(s2, 1).state = 1) { did -b s2 3 }
      if ($did(s2, 3).state = 1) { did -b s2 1 }
    }
    if ($did = 3) {
      if ($did(s2, 1).state = 1) { did -b s2 2 }
      if ($did(s2, 2).state = 1) { did -b s2 1 }
    }
  }
  if ($did(s2, $did).state = 0) {
    did -e s2 1
    did -e s2 2
    did -e s2 3
  }
}

More should be coded in this language! But there needs to be a way to make this into a real mess so it can be as good as Perl.

Edit: noticed that my Python-isms are leaking through and was able to reduce the code by 8 bytes!

afreak

Posted 2014-05-08T02:09:30.690

Reputation: 117

Haha, I like the intro to this one. It's kind of verbose though - could it be the beer speaking? =c) – Bruce Pierson – 2014-05-10T06:03:43.773

4

k3 - 95

a[`FAST`CHEAP`GOOD]:0
a[.;`c]:`check
a..l:"SELECT ANY TWO"
a..t:"if[3=+/a[];.[_v;_i;:;0]]"
`show$`a

code is here

sample run
(source: nsl.com)

Stevan Apter

Posted 2014-05-08T02:09:30.690

Reputation: 41

line 1: a dictionary with three variables; line 2: each variable is a checkbutton; line 3: label the dictionary; line 4: if three variables have been checked, reset the last variable checked to 0; line 5: show the dictionary. – Stevan Apter – 2015-10-19T14:57:03.480

Nice! Such a tragedy k4 has no GUI... – mollmerx – 2015-10-20T17:14:27.767

1k wins (but oh irony! 9 more characters are required in order to post!) – Stevan Apter – 2015-11-16T21:17:33.440

3

C#, 335 333 326 320 308

Based off Bobs Answer, mine does use fewer characters than his (335 v 342), but I might not understand fully how to count this.

using System.Linq;using System.Windows.Forms;class P:Form{static void Main(){new P();}P(){Text="SELECT ANY TWO";var a="FAST CHEAP GOOD".Split().Select(r=>new CheckBox{Text=r,Top=r[0]%9*20}).ToList();a.All(r=>{r.Validating+=(b,c)=>c.Cancel=a.Count(z=>z.Checked)>1;Controls.Add(r);return 1>0;});ShowDialog();}}

Ungolfed

using System.Linq;
using System.Windows.Forms;

class P : Form
{
    static void Main()
    {
        new P();
    }

    P()
    {
        Text = "SELECT ANY TWO";

        var a = "FAST CHEAP GOOD".Split().Select(r => new CheckBox
        {
            Text = r,
            Top = r[0] % 9 * 20
        }).ToList();

        //loops, I dont need no stinking loops
        a.All(r => { r.Validating += (b, c) => c.Cancel = a.Count(z => z.Checked) > 1; Controls.Add(r); return 1 > 0; });
        ShowDialog();
    }
}

iamkrillin

Posted 2014-05-08T02:09:30.690

Reputation: 280

Great use of anon functions and Linq here, especially like the Select. – Bruce Pierson – 2014-05-08T15:26:47.687

You can save a couple more characters by replacing the ==2 with a >1, and the true with a 1>0. You can also use a All instead of Where and Last. ToList is also shorter than ToArray. – Bob – 2014-05-09T11:57:20.260

@Bob Good call, don't know how I missed All(), and as a bonus, turns out with All you don't have to materialize it, saving even more – iamkrillin – 2014-05-09T12:06:32.407

3

Groovy - 357 221 217 chars

I've ported Quincunx's solution to Groovy 2.2.1, using SwingBuilder (and made it even more Groovier):

c=[];new groovy.swing.SwingBuilder().frame(){panel(){label("SELECT ANY TWO");f={if(c.count{it.isSelected()}>2)it.source.setSelected(1<0)};["FAST","CHEAP","GOOD"].each{c<<checkBox(label:it,itemStateChanged:f)}}}.show()

Ungolfed:

c=[]
new groovy.swing.SwingBuilder().frame() {
    panel() {
        label("SELECT ANY TWO")
        f = { if (c.count{it.isSelected()} > 2) it.source.setSelected(1<0) }
        ["FAST","CHEAP","GOOD"].each { c << checkBox(label: it, itemStateChanged: f) }
    }
}.show()

Michael Easter

Posted 2014-05-08T02:09:30.690

Reputation: 585

3

QML - 369 315 254 251 248 bytes

Here goes QML (QtQuick 2.0) version, given only the .qml file contents. This code requires Qt 5.1 at least to run. Not a big deal as its huge compared to other solutions (248 bytes), but it's a full featured cross-platform application (Android and iOs included)! :D

    import QtQuick 2.0;import QtQuick.Controls 1.1;Row{Text{text:"SELECT ANY TWO"}CheckBox{id:a;text:"FAST";enabled:!b.checked|!c.checked}CheckBox{id:b;text:"CHEAP";enabled:!a.checked|!c.checked}CheckBox{id:c;text:"GOOD";enabled:!b.checked|!a.checked}}

Horizontal layout dialog

To run it, save the code to a .qml file, install Qt 5.1 and run qmlscene.exe (or just qmlscene on linux), which will show an open file dialog. Chose the .qml file you've saved the code to and see the awesome result! :D

Eduard Sukharev

Posted 2014-05-08T02:09:30.690

Reputation: 141

2

JavaScript 209 (was 346)

Shortened: thanks for comments.

function f(){var a=document.getElementsByClassName("x"),n=0,i=0;for(i in a){if(a[i].checked)n++;}if(n<2){for(i in a){a[i].disabled=false;}}else{for(i in a){i(false===a[i].checked){a[i].disabled=true;break;}}}}

Golfed function:

function f(a,b,c){
var x=document.getElementById(a);
var y=document.getElementById(b);
var z=document.getElementById(c);
var n=0,i=0;
var a=[x,y,z];
for(i in a)
{
if(a[i].checked) n++;
}
if(n<2)
{
for(i in a)
{
a[i].disabled=false;
}
}
else
{
for(i in a)
{
if(false===a[i].checked)
{
a[i].disabled=true;
break;
}
}
}
}

HTML form: provides input and calls the function. * Form now uses class=x to group inputs.

<form>
        SELECT ANY TWO<br>
        FAST <input id="a" type="checkbox" class="x" value="0" onchange="f()"><br>
        CHEAP <input id="b" type="checkbox" class="x" value="1" onchange="f()"><br>
        GOOD <input id="c" type="checkbox" class="x" value="2" onchange="f()"><br>
    </form>

Tested with NetBeans and Chrome.

bacchusbeale

Posted 2014-05-08T02:09:30.690

Reputation: 1 235

You can golf the function further and reduce it to 264 characters by consolidating all of your vars, removing unnecessary braces and whitespace (including newline chars). You could probably get it smaller if you use an ES6 lambda. – Tony Ellis – 2014-05-08T08:07:58.837

Apart from some more obvious golfing, consider using a class to pull all of the input elements into an array in one hit instead, using getElementsByClassName eg. a=document.getElementsByClassName('q'). – Matt – 2014-05-08T08:28:25.417

change the ids to name and just call them with document.a, document.c, document.c also put them directly into a[] – frieder – 2014-05-08T11:25:26.880

2

JavaScript / jQuery 237 234 229

Very similar approach as Matt's answer, although a little longer.

$(function(){var e="input ",t="disabled",n,r;$("body").html("SELECT ANY TWO|FAST|CHEAP|GOOD".replace(/\|/g,"<"+e+'type="checkbox">'));n=$(e);n.change(function(){n.removeAttr(t);r=$(":checked");if(r.length>1)n.not(r).attr(t,t)})})

sshow

Posted 2014-05-08T02:09:30.690

Reputation: 133

2

Groovy

Based on the Java version, but much slimmed down ;)

Types were replaced by 'def', semicolons removed, add replaced by <<, the 1<0 replaced by 0, collect for creating the checkboxes, removed the itemevent type, removed casting the checkbox, enhanced the loops.

import java.awt.*
class F {
    def static main(a) {
        def f = new Frame()
        def p = new Panel()
        f << p
        p << new Label("SELECT ANY TWO")
        def c = ['FAST','CHECK','GOOD'].collect { new Checkbox(it) }
        c.each { b ->
            p << b
            b.addItemListener { e->
                int x = 0, i = 0
                3.times {
                    x += c[it].state ? 1 : 0
                }
                if (x > 2) {
                    e.source.state = 0                        
                }
            }
        }
        f.show()
    }
}

Erik Pragt

Posted 2014-05-08T02:09:30.690

Reputation: 121

Groovy is not java. That means that all those enhancements don't count as much. Everything you removed was necessary in java, but not groovy. – Justin – 2014-05-09T17:52:43.307

1You're right, Groovy is not Java, that why it's called Groovy. I'm not sure what you're trying to say here. – Erik Pragt – 2014-05-10T13:36:30.050

1

TCL 347

At least it beats Python and Java.

set d .
proc a v {upvar f f c c g g d d $v x
if $x&&$f+$c+$g==2 {set d .$f$c$g
$d configure -state disabled} 
if !$x {$d configure -state normal}}
set z -variable
set y -command
set x checkbutton
label .l -text {SELECT ANY TWO}
$x .011 -text FAST $z f $y a\ f
$x .101 -text CHEAP $z c $y a\ c
$x .110 -text GOOD $z g $y a\ g
pack .l .011 .101 .110

Note: if you start by selecting one checkbox and immediately unselecting it, you will get an error. You can fix it by adding 110 to the end of the first line.

Ungolfed:

# Keep track of the last disabled button. Set it to something valid to start with.
set last .110

proc toggled name {
        # Access some globals
        upvar fast  fast
        upvar cheap cheap
        upvar good  good
        upvar last  last
        upvar $name value

        # Just toggled one on, check if exactly two are now on
        if {$value == 1 && ($fast + $cheap + $good) == 2} {
                set last .$fast$cheap$good
                $last configure -state disabled
        }
        # Just toggled one off. Re-enable disabled one.
        if {$value == 0} {
                $last configure -state normal
        }
}

label .label -text {SELECT ANY TWO}

checkbutton .011 -text FAST  -variable fast  -command {toggled fast}
checkbutton .101 -text CHEAP -variable cheap -command {toggled cheap}
checkbutton .110 -text GOOD  -variable good  -command {toggled good}

pack .label .011 .101 .110

Kevin

Posted 2014-05-08T02:09:30.690

Reputation: 501

1

Javascript + Knockout: ~250 Characters

a=function(i){return "<input type=checkbox data-bind='value: "+i+", checked: x, disable: x().length>=2 && x().indexOf(\""+i+"\")==-1'>"},document.body.innerHTML = "SELECT ANY TWO"+a(0)+"Fast"+a(1)+"Good"+a(2)+"Cheap"; ko.applyBindings({x:ko.observableArray([])})

Origineil

Posted 2014-05-08T02:09:30.690

Reputation: 141

0

AngularJS - 155 (Demo)

SELECT ANY TWO :<i ng-init=t=[]><p ng-repeat="(i,v) in ['FAST','CHEAP','GOOD']"><input type=checkbox ng-disabled=t[(i+1)%3]&&t[(i+2)%3] ng-model=t[i]>{{v}}

The ungolfed version:

SELECT ANY TWO :
<i ng-init="checkedArray = []" /> <!-- A useless tag to initialize the array (which can't be done on the `input` tag, unfortunately) -->
<p ng-repeat="(key, value) in ['FAST', 'CHEAP', 'GOOD']">
    <input
        type="checkbox"
        ng-model="checkedArray[key]"
        ng-disabled="checkedArray[(key + 1) % 3] && checkedArray[(key + 2) % 3]"
    />
    {{value}}
</p>

Blackhole

Posted 2014-05-08T02:09:30.690

Reputation: 2 362

0

Ruby with Shoes, 133 characters

Shoes.app{para'SELECT ANY TWO'
$o=%w{FAST GOOD CHEAP}.map{|q|c=check{|c|$o[c]=!$o[c];$o.values.all?&&c.checked=p}
para q
[c,p]}.to_h}

Sample output:

Shoes window screenshot

manatwork

Posted 2014-05-08T02:09:30.690

Reputation: 17 865

0

FLTK, 303 characters

decl{int c;}Function{}{}{Fl_Window{}{xywh {9 9 195 195}}{Fl_Pack{}{label{SELECT ANY TWO}}{Fl_Check_Button{}{callback{e(o);}label FAST}Fl_Check_Button{}{callback{e(o);}label GOOD}Fl_Check_Button{}{callback{e(o);}label CHEAP}}}}Function{e(Fl_Button*o)}{}{code{if((c+=o->value()*2-1)>2){o->value(0);c--;}}}

Ungolfed:

decl { int c; }

Function {} {} {
    Fl_Window {} {
        xywh {9 9 195 195}
    } {
        Fl_Pack {} {
            label {SELECT ANY TWO}
        } {
            Fl_Check_Button {} {
                callback { e(o); }
                label FAST
            }
            Fl_Check_Button {} {
                callback { e(o); }
                label GOOD
            }
            Fl_Check_Button {} {
                callback { e(o); }
                label CHEAP
            }
        }
    }
}

Function { e(Fl_Button* o) } {} {
    code {
        if ((c += o->value() * 2 - 1) > 2) {
            o->value(0);
            c--;
        }
    }
}

Sample output:

FLTK window screenshot

manatwork

Posted 2014-05-08T02:09:30.690

Reputation: 17 865