I know you, but you don't know me

18

4

You're tasked with writing two programs. Program A must print out nothing on all inputs except when program B is input, in which case it should print 1. Program B must print out 1 on all inputs except when program A is input, in which case it should print nothing.

Scoring:

  • +1 For each character from both programs.
  • Lowest score wins.

ike

Posted 2014-01-09T20:14:13.533

Reputation: 1 753

3Is this quine-ish enough to tag it as [tag:quine]? It certainly seems so to me. – Justin – 2014-01-09T20:26:40.903

As the first two answers posted indicate, "being" another program is not terribly well defined in this descriptions. And, I'm with @Quincunx that this has something very much like the quine-nature. – dmckee --- ex-moderator kitten – 2014-01-09T22:25:52.940

@Quincunx I've added the quine tag. – Timtech – 2014-01-09T23:45:04.763

when you say it takes a program as input, do you mean it takes that program's source code as input or that program's output? – markasoftware – 2014-01-10T00:20:14.643

@Markasoftware The source code as input. – ike – 2014-01-10T00:29:17.503

@Quincunx A quine is a computer program which takes no input and produces a copy of its own source code as its only output. Neither program A nor B do that. – Brian Rogers – 2014-01-10T02:52:50.710

@BrianRogers However, to solve this problem, you have to use the same concept behind a quine. – Justin – 2014-01-10T03:21:01.467

1@Quincunx true, but nobody is doing that so far, unless you also call a quine any program that reads its source code from disk and prints it out :p – aditsu quit because SE is EVIL – 2014-01-10T04:59:04.293

2@aditsu I much dislike those answers. I think I'll post a very suboptimal answer that does not do that. I personally feel that reading source code through files is cheating; programs should work anywhere! – Justin – 2014-01-10T05:11:08.173

Ugh, my suboptimal answer is very difficult to debug. My head hurts like crazy – Justin – 2014-01-10T06:05:44.307

@Quincunx, I hear what you're saying about programs here that read their peers' code from disk. It's a shortcut, for sure. But consider a very real advantage: with such an approach, when you change code in A, you do not need to change B. The "purist" approach I think you're describing leaves both programs co-dependent on each other, doesn't it? i.e. if you make any to change A then you must also change B. Referencing is not as clever, but it is robust. :) – Darren Stone – 2014-01-10T09:40:35.990

Answers

5

GTB, 25

Executed from a TI-84 calculator

Program A

`_@_eq;"$w;&

Program B

`_@_eq;"$#w;&

Explanation

`_ Input a string

@_eq;" Check if it equals the source code (# is automatically stripped along with lowercase letters)

$w;& If so, display 1 (otherwise nothing) [for B it's $#w;& - if not, display 1 (otherwise nothing)]

Timtech

Posted 2014-01-09T20:14:13.533

Reputation: 12 038

12

Bash - 32 characters

Script A - 16 characters

cmp -s b&&echo 1

Script B - 16 characters

cmp -s a||echo 1

Usage

$> echo "foo" | ./a
$> cat b | ./a
1
$> echo "foo" ./b
foo ./b
$> cat a | ./b

JayQuerie.com

Posted 2014-01-09T20:14:13.533

Reputation: 333

5

Ruby, 54

A

$><<1if$<.read==IO.read(?B)

B

$><<1if$<.read!=IO.read(?A)

examples:

bash-3.2$ ruby A < A
bash-3.2$ ruby A < B
1bash-3.2$ ruby B < A
bash-3.2$ ruby B < B
1bash-3.2$ 

Darren Stone

Posted 2014-01-09T20:14:13.533

Reputation: 5 072

4

J (62)

Since you didn't forbid this...

Store the programs as A and B respectively.

Program A (30):

exit echo#~(1!:1<'B')-:1!:1[3

Program B (32):

exit echo#~-.(1!:1<'A')-:1!:1[3

How it works (Program B, A is similar):

  • 1!:1[3: read stdin
  • 1!:1<'A': read file A
  • -:: see if they are equal
  • -.: negate the result
  • #~: replicate the result by itself (so, 1 results in one 1 and 0 results in zero 0s, i.e. nothing)
  • echo: output
  • exit: exit (the J interpreter does not exit by default when it reaches the end of the file)
$ jconsole A <B
1
$ jconsole A <foo
$ jconsole B <A
$ jconsole B <foo
1
$

marinus

Posted 2014-01-09T20:14:13.533

Reputation: 30 224

Can you give a short explanation of what this does? – ike – 2014-01-09T20:39:11.277

@ike: did so _______ – marinus – 2014-01-09T20:43:52.047

3

Haskell - WITHOUT loading source - 478 644 characters

This assumes getContents ALWAYS ends with a newline and so drops the final character without checking because I don't feel like escaping it

A

main=interact$($'1').replicate.(1-).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='-'='*'|n=='*'='-'|True=n;d="main=interact$($'1').replicate.(1-).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='-'='*'|n=='*'='-'|True=n;d="

B

main=interact$($'1').replicate.(1*).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='*'='-'|n=='-'='*'|True=n;d="main=interact$($'1').replicate.(1*).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='*'='-'|n=='-'='*'|True=n;d="

It works like a standard quine, but swapping - for * to get the other program (avoiding those characters elsewhere).

The following test prints as expected (replacing main=interact$ with a= and b=)

main=do
  putStrLn "START"
  putStrLn$a "FOO"
  putStrLn$a "main=interact$($'1').replicate.(1*).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='*'='-'|n=='-'='*'|True=n;d=\"main=interact$($'1').replicate.(1*).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='*'='-'|n=='-'='*'|True=n;d=\"\n"
  putStrLn$b "FOO"
  putStrLn$b "main=interact$($'1').replicate.(1-).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='-'='*'|n=='*'='-'|True=n;d=\"main=interact$($'1').replicate.(1-).fromEnum.(/=map r(d++shows d[toEnum 10]))where r n|n=='-'='*'|n=='*'='-'|True=n;d=\"\n"
  putStrLn "END"

-

START

1
1

END

Toeofdoom

Posted 2014-01-09T20:14:13.533

Reputation: 171

Also if there's a preferred way to format monolithic single line functions that would be handy, http://meta.stackexchange.com/questions/22186/how-do-i-format-my-code-blocks doesn't appear to cover it

– Toeofdoom – 2014-01-10T14:08:31.303

2

Python 2.7 - 82

File A (literally named just a):

if raw_input()==open('b').read():print 1

File B (literally named just b):

if raw_input()!=open('a').read():print 1

user8777

Posted 2014-01-09T20:14:13.533

Reputation:

Total abuse there without the .py - does that even work? – Timtech – 2014-01-09T23:41:12.890

I'm sure @LegoStormtroopr would be running in the same manner as my Ruby examples posted here, a few minutes earlier. ;-) – Darren Stone – 2014-01-09T23:55:55.920

1@Timtech It does if you run them from the command line as python a. – None – 2014-01-10T00:17:39.463

I meant is it possible to even generate a file without an extension? – Timtech – 2014-01-10T00:21:35.217

5Of course it is? If you are on a Posix machine touch a will create an empty file if you have permissions. For extra cruel fun you can even do touch \~ which creates a file named with a single tilde (~) - then watch as someone foolhardedly tries to remove it ;) – None – 2014-01-10T00:35:21.900

2

Ruby, 166 chars, no reading source

A:

(gets(p)==<<2.tr('&|','|&')*2+'2')&&p(1)
(gets(p)==<<2.tr('&|','|&')*2+'2')&&p(1)
2

B:

(gets(p)==<<2.tr('|&','&|')*2+'2')||p(1)
(gets(p)==<<2.tr('|&','&|')*2+'2')||p(1)
2

Make sure your text editor doesn't save with a trailing newline.

Usage (example):

 $ ruby know_a.rb know_b.rb 
1
 $ ruby know_a.rb know_a.rb 
 $ ruby know_b.rb know_a.rb 
 $ ruby know_b.rb know_b.rb 
1

Each program constructs the source of the other program using a HEREdoc and string transforms, then compares the result to the input.

histocrat

Posted 2014-01-09T20:14:13.533

Reputation: 20 600

This was easy enough to write, but now some part of my brain that doesn't understand recursion is insisting it can be optimized but has no idea how. – histocrat – 2014-01-10T20:05:50.637

What is p? And where does the heredoc end? – aditsu quit because SE is EVIL – 2014-01-10T21:32:13.390

p is a built-in ruby method that prints the arguments passed to it, then returns those arguments, making it useful for golfed output. When called with no arguments it returns nil. The argument to gets is a delimiter, so passing p results in a nil delimiter which means it reads STDIN until it gets to EOF. The heredoc expression is <<2, so it ends at (and does not include), the 2 at the end of the file. – histocrat – 2014-01-10T21:40:04.587

The use of 2 as the heredoc delimiter is a traditional bit of obfuscation. It can be almost any string. – histocrat – 2014-01-10T21:43:18.247

Is the content of the heredoc evaluated somehow? – aditsu quit because SE is EVIL – 2014-01-10T21:49:58.260

Nope, it's just a string (that happens to be identical to the first line of code). <<2 returns the middle line, which we then call tr on to switch the '&' and '|' characters, then concatenate to itself via *2, then concatenate '2' to. We compare the resulting string to the result of gets(p), which is the input file. – histocrat – 2014-01-10T22:03:55.197

How can you call tr and all the other stuff if they are just part of your heredoc string? The way I see it, both your programs are: unbalanced (, compare gets(p) (whole input, I suppose) with static heredoc string, the end. – aditsu quit because SE is EVIL – 2014-01-10T22:07:07.207

The Ruby parser is extremely forgiving. It treats <<2.tr the same as (<<2).tr, which is to say that 2 is the heredoc delimiter string and everything after it (on the same line) is more code. The heredoc string doesn't start until the next line. – histocrat – 2014-01-10T22:12:03.377

Oh God, that's horrible... and kinda cool. I'll see if I can figure out the &| vs |& stuff. – aditsu quit because SE is EVIL – 2014-01-10T22:14:10.177

Ok I think I got it, very clever! Too bad you can't add the number 2 directly. – aditsu quit because SE is EVIL – 2014-01-10T22:24:40.607

1

Python 3 - 102 characters

Prints 1 if the input is the same as program 2, otherwise nothing:

if input()==open('a.py').read():print('1')

Prints 1 if input is not the same as program 1, otherwise nothing:

if input()==open('a.py').read():print('1')

user10766

Posted 2014-01-09T20:14:13.533

Reputation:

Can't the whitespace be removed? Also you can shorten the scripts from t.py and tt.py to a.py and b.py. – Timtech – 2014-01-10T01:28:24.683

@Timtech Sure, good idea. Also, I wasn't counting white-space - that is just there for readability. The new-lines cannot be removed though. – None – 2014-01-10T01:40:01.640

Yes, I am aware of Python's newline sensitivity. – Timtech – 2014-01-10T02:33:07.097

Only one of the newlines can really be removed, that after the colon. The others would need semicolons added, so there is no advantage to removing those newlines. – AJMansfield – 2014-01-10T02:39:37.137

@AJMansfield Yes, I know, but I didn't count newlines anyway. – None – 2014-01-10T02:40:26.140

@user2509848, if you cannot remove newlines or whitespaces then it is conventional to include those characters in your byte count. You will find these conventions used in nearly everyone's counts and there are discussions about this on meta. Each of your programs above can be reduced to 4 lines so that requires an additional 3 newlines each to separate the lines. I would suggest +6 chars. But I would really suggest eliminating those variable assignments. – Darren Stone – 2014-01-10T09:28:25.280

@user2509848 I just fixed what he was talking about; the new programs don't need any newlines at all. – AJMansfield – 2014-01-11T00:28:12.920

@AJMansfield Thanks. Your edit was rejected, but I got the code and changed it anyway. – None – 2014-01-11T01:25:14.443

1

Haskell - 138

Not really a good answer, but wanted to make both programs use the same source. Could save some chars by renaming the file, but it's not going to make this a winning solution so I don't think it's worth it.

import System.Environment
import Control.Monad
main=do{i<-getContents;p<-getProgName;f<-readFile "ab.hs";when((f==i)/=(p=="B"))(print 1)}

Compile this source as both A and B.

Test:

% ghc -o A ab.hs
[1 of 1] Compiling Main             ( ab.hs, ab.o )
Linking A ...
% cp A B
% ./A < ab.hs
1
% ./B < ab.hs
% ./A < ab.hi
% ./B < ab.hi
1

shiona

Posted 2014-01-09T20:14:13.533

Reputation: 2 889

why compile twice into A, and then copy A to B? – mniip – 2014-01-09T22:45:19.637

That was a mistake by my part when copypasting the code. Thanks for pointing that out. Will fix. – shiona – 2014-01-09T22:46:09.930

1

Node.js - 142 characters

Script | (otherwise known as Script A) - 80 characters

f=require('fs').readFileSync;f('/dev/stdin','hex')==f('&','hex')&&console.log(1)

Script & (otherwise known as Script B) - 62 characters

eval(require('fs').readFileSync('|','utf8').replace(/&/g,'|'))

Usage

# \| is Script A
# \& is Script B

$> echo "foo" | node \| 
$> cat \& | node \| 
1
$> echo "foo" | node \& 
1
$> cat \| | node \&

Description

Script B reads the contents of Script A and evals it after swapping the file names and the and operator to an or.

I named the files & and | so I can perform a single replace in Script B.

JayQuerie.com

Posted 2014-01-09T20:14:13.533

Reputation: 333

0

bash/grep — 59 chars

51 chars if we only count the actual program string.

$ a='grep -cx "$b" | grep -x 1'
$ b='grep -vcx "$a" | grep -x 1'
$ echo 'foo' | eval $a
$ echo $b | eval $a
1
$ echo 'foo' | eval $b
1
$ echo $a | eval $b

Andrew Cheong

Posted 2014-01-09T20:14:13.533

Reputation: 405

-1

R (62 chars)

i=identical
A=function(x)if(i(x,B))1
B=function(x)if(!i(x,A))1

produces:

> A(123)
> A(A)
> A(B)
[1] 1
> B(123)
[1] 1
> B(A)
> B(B)
[1] 1

Meta comment: R fairs relatively bad on code golf as there is no shortcut to function...

Henrik

Posted 2014-01-09T20:14:13.533

Reputation: 169