Does the string contain 2016?

-3

Given a string input, your task is to write a program that prints a truthy value to STDOUT or equivalent if the input contains "2016" anywhere in it without using any built-in contains, match, replace, split or other functions that use patterns or regexes.

A truthy value also must be printed if the input contains "2016" with the same number of spaces between each number.

Test Cases

2016
    => true
"2016"
    => true
2202012016016166
      ^^^^ => true
220201 2 0 1 6 016166
    => true
Happy New Year! It's 2016!
    => true
2016 is coming!
    => true

2_0_1_6
    => false
22001166
    => false
It's not 2015 any more
    => false
6102
    => false
201.6
    => false
20 16
    => false
2 0  1   6
    => false

Rules

  • Regexes and pattern matching cannot be used
  • Built-in contains, match, and replace cannot be used
  • Built-in split functions cannot be used (the only exception is when splitting the string into individual characters for looping through them, such as input.split(""))
  • The code cannot contain the string "2016" in any form (unicode literals and constructing the string included - that doesn't mean that the characters 0, 1, 2, or 6 can't be used)
  • The input may either be taken from STDIN or as an argument to a function
  • It is safe to assume that the input will not contain linefeeds or newlines.
  • The input may contain any printable ASCII characters (spaces included)
  • A truthy value must be printed to STDOUT or equivalent if the input contains 2016.
  • A falsey value must be printed to STDOUT or equivalent if the input does not contain 2016
  • If using a function, instead of using STDOUT, the output can be the return value of the function
  • The truthy/falsey value cannot be printed to STDERR.
  • Standard loopholes apply
  • This is , so the shortest program in bytes wins. Good luck!

Bonus

-30 Bytes if the input also returns a truthy value if the spaces between the characters in 2016 are the same.

Happy 2 0 1 6
    => true
I can't wait for  2   0   1   6
    => true
It's almost 2 0  1   6
    => false

Leaderboard

This is a Stack Snippet that generates both a leaderboard and an overview of winners by language.

To ensure your answer shows up, please start your answer with a headline using the following Markdown template

## Language Name, N bytes

Where N is the size, in bytes, of your submission

If you want to include multiple numbers in your header (for example, striking through old scores, or including flags in the byte count), just make sure that the actual score is the last number in your header

## Language Name, <s>K</s> X + 2 = N bytes

var QUESTION_ID=67575;var OVERRIDE_USER=20634;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"http://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(-?\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

Jojodmo

Posted 2015-12-24T01:06:55.240

Reputation: 1 569

Question was closed 2015-12-24T04:06:20.580

3It's too vague what built ins are allowed. For example, can I split on 2016 and check if the result has multiple parts? What about a builtin that checks if a string is a prefix of another string? – xnor – 2015-12-24T01:22:36.843

So that means a.split("") is invalid? – Conor O'Brien – 2015-12-24T01:28:15.050

I don't know what that means for my examples. I was thinking of split on a fixed string – xnor – 2015-12-24T01:29:12.133

@CᴏɴᴏʀO'Bʀɪᴇɴ I updated the challange - I assumed that all languages had a function to get the individual characters of a string – Jojodmo – 2015-12-24T01:30:24.783

2Ok, then can I use join to intersperse a string with spaces? Slice a string at some position? Check if strings are equal? It would be nice to have a criterion for the boundary rather than checking case by case. – xnor – 2015-12-24T01:36:14.807

@xnor You can do all of those things, because they are not disallowed in the rules (join can only be used if it doesn't use a regex though, again, like stated in the rules) – Jojodmo – 2015-12-24T01:37:11.063

Are we allowed to, for example, do str(2016) (string representation of 2016)? Technically that doesn't contain the string 2016. – PurkkaKoodari – 2015-12-24T01:40:39.950

@Pietu1998 I included that part only to close any loopholes that may appear - but no, as it is constructing the string "2016" – Jojodmo – 2015-12-24T01:41:29.637

Can I construct the string "2 0 1 6"? – Lynn – 2015-12-24T01:49:36.310

@Mauris You found a loophole in the loophole closer... Anyways, I don't see any reason why you shouldn't be able to, so yes, you can construct 2 0 1 6 – Jojodmo – 2015-12-24T01:51:25.623

This challenge has a close vote for Unclear what you're asking? I feel like its very clear what this challenge is asking - check if a string contains another string without directly using built-in functions that make it easy – Jojodmo – 2015-12-24T01:52:05.773

4I think they mean it's unclear what code you're asking them to produce because of the vague rules about what built-ins are allowed, no string constructing, etc... – user81655 – 2015-12-24T02:02:32.833

2"pattern matching cannot be used" - that rules out Haskell. I was working on a solution, but now I'm out. – nimi – 2015-12-24T02:12:31.590

1"pattern matching cannot be used" - pattern matching is the entire premise of Mathematica. Expressions are matched with patterns, then evaluated. – LegionMammal978 – 2015-12-24T02:58:26.500

@LegionMammal978 I can't tell if you're being serious or not... You're taking it *way* too literally - "pattern matching can't be used" doesn't mean that the language can't be pattern matched, it means that you can't use pattern matching in your code – Jojodmo – 2015-12-24T03:01:11.313

6-1; rules are ad-hoc and arbitrary – lirtosiast – 2015-12-24T03:08:43.367

@ThomasKwa I guess that's opinion, but I don't see how they're arbitrary - the rules all enforce that users can't just do if(input.contains("2016")){return true;} - I didn't just through random rules in there for no reason – Jojodmo – 2015-12-24T03:10:38.137

7The addition of many arbitrary-looking rules often means that a challenge is uninteresting or flawed. – lirtosiast – 2015-12-24T03:30:33.633

@ThomasKwa I didn't really think that there were that many rules, but I guess if that many people agree with you, I should probably update the challenge... The "spaces" part is now a bonus, and is not required – Jojodmo – 2015-12-24T04:14:04.300

The main problem is that the rules are not "black-and-white" for every language. I thought it was an interesting challenge (for my preferred language, JavaScript, at least) but for others that rely heavily on pattern-matching the rules become less clear. The only time that challenges with arbitrary rules (rules that prevent something which would normally not be an issue) work is when they are clear across all languages. Unfortunately the pattern matching rule here may only be clear if it is spelled out for each individual language (which is not feasible). – user81655 – 2015-12-24T04:32:58.977

@user81655 Yes, the rules have a lot of grey area. I had the same pattern matching restriction on another one of my challenges, but I assume that went over well because the objective was much more clear.

– Jojodmo – 2015-12-24T04:35:21.957

2Maybe the challenge would have been better received if it had a simple rule like "No regular expressions" like the other one had, but there are other loopholes (like the reasons you disallowed the "2016" literal and certain built-ins). Too many arbitrary rules to prevent loopholes and people won't like the challenge. – user81655 – 2015-12-24T04:44:50.450

Answers

1

CJam, 35 - 30 = 5 bytes

qS*_,,_Sf*{"2 0 1 6"\*}%\:)@few:+&`

Explanation

qS*                                   Push s p a c e d   i n p u t.
   _,,                                Push [0..N-1] where N = len(input).
      _Sf*                            Push ["", " ", "  ", "   ", ...].
          {"2 0 1 6"\*}%              Make it ["2 0 1 6", "2   0   1   6", ...].
                        \             Swap [0..N-1] to top of stack.
                         :)           Increment each, giving [1..N].
                           @          Rotate spaced input I to top of stack.
                            few       Push [I1ew I2ew .. INew], i.e.
                               :+      when concatenated, all substrings of I.
                                 &    Intersect sets.
                                  `   Print as CJam syntax.

Essentially, given an input string abcd, this executes a "substring search" by intersecting the sets:

  • 2 0 1 6, 2 0 1 6, ... up to 2*len(input())-1 = more than enough spaces,
  • a, , b, ..., a b, ... a b c d.

If a result is found, such a spaced 2016 string appeared as a substring of the input, and a truthy list containing this result is printed, like ["2 0 1 6"]. Otherwise, the empty list is printed.

The string "2016" is never constructed as the code runs; only its spaced-out versions are.

Lynn

Posted 2015-12-24T01:06:55.240

Reputation: 55 648

1

JavaScript (ES6), 125 - 30 = 95 bytes

x=>(y=[...x]).map((_,i)=>y.map((_,j)=>r?0:(n=x.substr(j,a.length),r=n<a&n>b),s=" ".repeat(i),a=2+s+0+s+1+s,b=a+5,a+=7),r=0)|r

Explanation

Returns 1 if it matched, otherwise 0.

Brute forces every possible combination of spaces between 2016 and checks for a match at each substring. Note that it never constructs the string 2016 because it generates a as 2017 and b as 2015 (both with spaces) and checks if b < substring < a.

x=>                             // x = input string
  (y=[...x])                    // y = input as array
  .map((_,i)=>                  // loop over every possible amount of spaces between digits
    y.map((_,j)=>               // loop over every character to check for a match
      r?0:(                     // if r is set we don't have to do anything, if not:
        n=x.substr(j,t.length), // n = substring to compare
        r=n<a&n>b               // check if r is 2016
      ),
      s=" ".repeat(i),          // s = spaces between letters
      a=2+s+0+s+1+s,            // get string to compare with
      b=a+5,                    // b = 2015 (with spaces)
      a+=7                      // a = 2017 (with spaces)
    ),
    r=0                         // r = result
  )
  |r                            // return result

Test

var solution = x=>(y=[...x]).map((_,i)=>y.map((_,j)=>r?0:(n=x.substr(j,a.length),r=n<a&n>b),s=" ".repeat(i),a=2+s+0+s+1+s,b=a+5,a+=7),r=0)|r
<input type="text" id="input" value="I can't wait for  2   0   1   6" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

user81655

Posted 2015-12-24T01:06:55.240

Reputation: 10 181

It looks like this returns false for the input "220201 2 0 1 6 016166" - I should probably add that as a test case – Jojodmo – 2015-12-24T02:20:09.157

@Jojodmo You're right. I changed to a brute-force approach because it was shorter than fixing my old method. – user81655 – 2015-12-24T03:02:12.393

0

Swift 2, 307 297 - 30 = 267 Bytes

func d(s:String)->Int{var c=0;var n=0;var l=0;for v in s.characters{if(v=="2"){c=1;l=0;n=0};if(c==1&&v=="0"){c=2;l=n;n=0};if(c==2&&v=="1"){c=(l==n ?3:0);l=n;n=0};if(c==3&&v=="6"){if(l==n){return 1}else{c=0}};if(!(v=="2" || v=="0" || v=="1" || v=="6")){if(v==" "){n++}else{c=0;l=0;n=0;}}};return 0}

Ungolfed

func d(s: String) -> Int{
    var c=0
    var n=0
    var l=0
    for v in s.characters{
        if(v == "2"){
            c = 1
            l = 0
            n = 0
        }
        if(c == 1 && v == "0"){
            c = 2
            l = n
            n = 0
        }
        if(c == 2 && v == "1"){
            c = (l == n ? 3 : 0)
            l = n
            n = 0
        }
        if(c == 3 && v == "6"){
            if(l == n){
                return 1
            }
            else{
                c = 0
            }
        }
        //you may be wondering why I didn't use &&. It's because
        //using && would require me to use !=, which needs spaces
        //on both sides
        if(!(v == "2" || v == "0" || v == "1" || v == "6")){
            if(v == " "){
                n++
            }
            else{
                c=0
                l=0
                n=0
            }
        }
    }
    return 0
}

Jojodmo

Posted 2015-12-24T01:06:55.240

Reputation: 1 569