การกำหนดหมายเลขหน้าสไตล์ xkcd


65

หนังสือของ Randall Munroe "xkcd, volume 0" ใช้ระบบตัวเลขที่ค่อนข้างแปลกสำหรับหมายเลขหน้า หมายเลขหน้าสองสามครั้งแรกคือ

1, 2, 10, 11, 12, 20, 100, 101, 102, 110, 111, 112, 120, 200, 1000, 1001, ...

นี้มีลักษณะบิตเช่น ternary แต่สังเกตเห็นว่าเขาข้ามจาก20ตรงไปยัง100จาก120ไป200และกลับจากไป200 1000วิธีหนึ่งในการกำหนดลำดับนี้คือการบอกว่ามันระบุหมายเลข ternary ทั้งหมดที่มีมากที่สุดคนหนึ่ง2และไม่มีการหลังจากนั้น1 2คุณสามารถค้นหานี้ใน OEIS ในรายการA169683 ระบบตัวเลขนี้เป็นที่รู้จักกันไบนารีลาด

งานของคุณคือการหาการแสดงจำนวนเต็มบวกที่กำหนดNในระบบจำนวนนี้

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ของฟังก์ชันและส่งผลลัพธ์ผ่าน STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด), ค่าส่งคืนของฟังก์ชันหรือพารามิเตอร์

เอาท์พุทอาจจะเป็นสตริงจำนวนที่มีการแทนทศนิยมเท่ากับการเป็นตัวแทนไบนารีเอียงหรือรายการของตัวเลข (เป็นจำนวนเต็มหรือตัวอักษร / สตริง) คุณต้องไม่ส่งคืนเลขศูนย์นำหน้า

นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

สนุกจริง:มีบุญบางอย่างในระบบตัวเลขนี้ เมื่อเพิ่มตัวเลขคุณจะเปลี่ยนตัวเลขที่อยู่ติดกันสูงสุดสองหลักเสมอ - คุณจะไม่ต้องเปลี่ยนตัวเลขทั้งหมด ด้วยการเป็นตัวแทนที่ถูกต้องที่ช่วยให้การเพิ่มขึ้นใน O (1)

กรณีทดสอบ

1 => 1
2 => 2
3 => 10
6 => 20
7 => 100
50 => 11011
100 => 110020
200 => 1100110
1000 => 111110120
10000 => 1001110001012
100000 => 1100001101010020
1000000 => 1111010000100100100
1048576 => 10000000000000000001

1000000000000000000 => 11011110000010110110101100111010011101100100000000000001102

ฉันจะให้คำตอบที่สั้นที่สุดซึ่งสามารถแก้ปัญหากรณีทดสอบครั้งสุดท้าย (และข้อมูลอื่น ๆ ที่มีขนาดใกล้เคียงกันดังนั้นอย่าคิดถึง hardcoding) ในเวลาน้อยกว่าหนึ่งวินาที

ลีดเดอร์

นี่คือตัวอย่างข้อมูลเพื่อสร้างทั้งกระดานผู้นำปกติและภาพรวมของผู้ชนะตามภาษา

เพื่อให้แน่ใจว่าคำตอบของคุณปรากฏขึ้นโปรดเริ่มคำตอบด้วยหัวข้อโดยใช้เทมเพลต Markdown ต่อไปนี้:

# Language Name, N bytes

ที่Nมีขนาดของส่งของคุณ หากคุณปรับปรุงคะแนนของคุณคุณสามารถเก็บคะแนนเก่าไว้ในพาดหัวโดยการตีพวกเขาผ่าน ตัวอย่างเช่น

# Ruby, <s>104</s> <s>101</s> 96 bytes

<script>site = 'meta.codegolf'; postID = 5314; isAnswer = true; QUESTION_ID = 51517</script><script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>jQuery(function(){var u='https://api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)</code></pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>


32
ฉันมีหนังสือเล่มนั้นมาตั้งแต่ครั้งแรกที่ออกมาและไม่เคยสังเกตเห็นหมายเลขหน้า
Alex A.

2
@AlexA ฉันติดไว้ที่ Kindle แล้วซึ่งคุณไม่สามารถทำเลขหน้าใด ๆ ที่น่าสนใจได้
LegionMammal978

21
@ LegionMammal978: โศกนาฏกรรม
Alex A.

1
@ SuperJedi224 ฉันทามติดูเหมือนว่าจะไม่เป็นเช่นนั้นขอโทษ (ฉันได้รับการยกเว้นจากฉันทามติหากนั่นเป็นเพียงการป้อนข้อมูลแบบเดียวกับที่ภาษาของคุณสามารถจัดการได้
Martin Ender

4
สิ่งนี้ทำให้ฉันนึกถึงวิธีที่ฉันเคยนับเมื่อฉันอายุ 3 ขวบฉันให้เหตุผลว่า: "ไม่มีสิบห้าสิบดังนั้นหลังจากหนึ่งร้อยเก้าต้องเป็นสองร้อย" ฉันเพียง แต่ตระหนักถึงความผิดพลาดของฉันเมื่อเห็นความแตกต่างระหว่าง59->60และ109->110ด้วยส่วนเสริมพิเศษ 0
Cyoce

คำตอบ:


12

Pyth, 17 ไบต์

Ljb3ye.f!-P-yZ01Q

นี่ค่อนข้างช้าน่าขัน - O(output^log_2(3)). มันเป็นเลขชี้กำลังในความยาวของอินพุต แต่ไม่ได้ทวีคูณเป็นทวีคูณเช่นคำตอบบางอย่างบนหน้าเว็บ ความคิดบางอย่างที่นำมาจากคำตอบ @ เดนนิส, ที่นี่

สาธิต.

มันใช้ประโยชน์จาก.fฟังก์ชัน "ลูปของ Pyth จนกระทั่งพบการจับคู่ n"


32

CJam, 24 23 22 21 19 ไบต์

ri_)2b,,W%{2\#(md}/

นี่เป็นวิธีการO (บันทึก n)โดยที่nคืออินพุตที่ทำกรณีทดสอบล่าสุดเสร็จสมบูรณ์ทันที มันจะแปลงnโดยตรงไปยังลาดไบนารีโดยใช้ส่วนโมดูลาร์ด้วยค่าของหลัก1

รหัสนี้เสร็จสิ้นด้วยความผิดพลาดที่จะไป stderr กับล่าม Java ซึ่งได้รับอนุญาตตามที่สอดคล้องกับ Meta

หากคุณลองใช้รหัสนี้ในล่าม CJamให้ละเว้นทุกสิ่งยกเว้นบรรทัดสุดท้ายของผลลัพธ์

ข้อผิดพลาดสามารถกำจัดได้ในราคา 2 ไบต์โดย2>ต่อW%ท้าย

ขอบคุณ @ MartinBüttnerสำหรับการตีหนึ่งไบต์

พื้นหลัง

แทน binary ลาดkที่ ... 0สอดคล้องกับจำนวนเต็มn = (2 + 1 k -1) กk + ... + (2 1 -1 บริการ) 0

เนื่องจากทั้งสอง(2 k -1) + ... + (2 1 -1) = 2 k + 1 - (k + 2)และ(2 k -1) + ... + 2 (2 j -1) = 2 + 1 k - (2 เจ + 1 - 2 J + K + 1)น้อยกว่า2 + 1 k -1ค่าของkเพื่อ0สามารถกู้คืนโดยส่วน modular ต่อเนื่องโดย2 + 1 k -1 , 2 k -1ฯลฯ

ในการเริ่มต้นเราต้องหาค่า2 k + 1 -1ก่อน ตั้งแต่nที่มากที่สุด2 แห่ง (2 + 1 k -1) , เลข1 + nจะต้องเป็นอย่างเคร่งครัดมีขนาดเล็กกว่า2 k + 2

ดังนั้นการเป็นส่วนหนึ่งของจำนวนเต็มของลอการิทึมไบนารีของ1 + nผลตอบแทนถัวเฉลี่ยk + 1

สุดท้ายเราสังเกตว่าจำนวนเต็มn + 1มี⌊log 2 (n + 1) ⌋ดิจิตในฐาน 2

มันทำงานอย่างไร

ri    e# Read an integer N from STDIN.
2b,   e# Push the number of binary digits of N + 1, i.e, K + 2 = log(N + 1) + 1.
,W%   e# Push the range [K+1 ... 0].
{     e# For each J in the range:
  2\# e#   J -> 2**J
  (   e#     -> 2**J - 1
  md  e#   Perform modular division of the integer on the stack (initially N)
      e#   by 2**J - 1: N, 2**J - 1 -> N/(2**J - 1), N%(2**J - 1)
}/    e#

ในช่วงสองซ้ำที่ผ่านมาเราดำเนินการแบ่งแบบแยกส่วนโดย1และ0 อันแรกผลัก0 ที่ไม่พึงประสงค์ในกอง ความพยายามครั้งสุดท้ายที่จะดำเนินการ0 0 mdซึ่งปรากฏทั้ง0วินาทีที่ไม่ต้องการออกจากสแต็กออกจากทันทีแทนที่จะผลักอะไรและทิ้งสแต็กไปที่ STDOUT


28

Python 2, 67 ไบต์

def f(n):x=len(bin(n+1))-3;y=2**x-1;return n and n/y*10**~-x+f(n%y)

ดูเหมือนว่าจะทำงานสำหรับกรณีทดสอบที่กำหนด หากฉันได้รับสิ่งนี้ถูกต้องน่าจะเป็นไปได้O(place values set in output)ดังนั้นมันจึงเป็นกรณีสุดท้ายได้อย่างง่ายดาย

f(100)โทรเช่น ส่งคืนการแทนค่าทศนิยมเท่ากับไบนารีที่เอียง

Python 3, 65 ไบต์

def g(n,x=1):*a,b=n>x*2and g(n,x-~x)or[n];return a+[b//x,b%x][:x]

มีประสิทธิภาพน้อยกว่าเล็กน้อย แต่ยังคงเป็นลอการิทึมดังนั้นกรณีสุดท้ายจึงใกล้เข้ามาทันที

g(100)โทรเช่น ส่งคืนรายการตัวเลข


ไม่2andรวบรวมใน 3 หรือไม่? ฉันอยู่ใน 2 และ2and2ส่งข้อผิดพลาดทางไวยากรณ์
TankorSmash

3
@TankorSmash 2and2ไม่ทำงานเพราะมันจะถูกแยกวิเคราะห์เป็น2 and2- ลอง2and 2ซึ่งควรจะทำงานได้ถ้าเวอร์ชั่น Python ของคุณใหม่พอ (ทดสอบใน Python 2.7.10)
Sp3000

โอ้ดีคุณพูดถูก แม้แต่ใน 2.7.3 ก็ใช้งานได้
TankorSmash

12

CJam, 22 21 20 bytes

ri_me,3fb{0-W<1-!},=

นี่เป็นวิธีO (e n n)โดยที่nคืออินพุต โดยจะแสดงเป็นครั้งแรก⌊e n integers เชิงลบในฐาน 3 กำจัดผู้ที่มี2หรือ1หลังจากครั้งแรกที่2 (ถ้ามี) และเลือก1 + n TH

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

ri    e# Read an integer N from STDIN.
_me,  e# Push [0 ... floor(exp(N))-1].
3fb   e# Replace each integer in the range by the array of its digits in base 3.
{     e# Filter; for each array A:
  0-  e#   Remove all 0's.
  W<  e#   Remove the last element.
  1-  e#   Remove all 1's.
  !   e#   Logical NOT. Pushes 1 iff the array is empty.
},    e#   If ! pushed 1, keep the array.
=     e# Select the (N+1)th element of the filtered array.

9

Pyth, 20 ไบต์

Jt^2hslhQ#p/=%QJ=/J2

ทำงานใน O (บันทึก (อินพุต ())) ต่ำกว่าหนึ่งวินาทีสำหรับกรณีทดสอบขั้นสุดท้าย ตามรอบการวิ่งจนกระทั่งเกิดข้อผิดพลาดวนรอบ ไม่มีการขึ้นบรรทัดใหม่

สาธิต.

คำอธิบาย:

Jt^2hslhQ#p/=%QJ=/J2
                        Implicit: Q is the input.
      lhQ                          log(Q+1,2)
     slhQ                    floor(log(Q+1,2))
    hslhQ                    floor(log(Q+1,2))+1
  ^2hslhQ                 2^(floor(log(Q+1,2))+1)
 t^2hslhQ                 2^(floor(log(Q+1,2))+1)-1
Jt^2hslhQ               J=2^(floor(log(Q+1,2))+1)-1
         #              until an error is thrown:
            =%QJ        Q=Q%J
                =/J2    J=J/2
           /            The value Q/J, with the new values of Q and J.
          p             print that charcter, with no trailing newline.

J ถูกกำหนดค่าเริ่มต้นให้กับค่าของตำแหน่งเลขฐานสองแบบเอียงขนาดเล็กที่สุดซึ่งใหญ่กว่าอินพุต จากนั้นทุกครั้งที่ผ่านลูปเราจะทำสิ่งต่อไปนี้:

  • นำหลักของแต่ละค่าJจากที่มีQ =%QJตัวอย่างเช่นถ้าQ=10และJ=7, Qกลายเป็น3ซึ่งสอดคล้องกับการเปลี่ยนแปลงไบนารีเอียงจากไป110 10สิ่งนี้ไม่มีผลในการทำซ้ำครั้งแรก
  • เปลี่ยนค่าต่อไปมีขนาดเล็กลาดไบนารีฐานJ =/J2นี่คือการหารแบบพื้นโดย 2 ซึ่งJ=7จะเปลี่ยนJ=3เป็นตัวอย่าง เนื่องจากสิ่งนี้เกิดขึ้นก่อนที่ตัวเลขแรกจะถูกเอาท์พุททำให้Jมีตำแหน่งหลักหนึ่งตำแหน่งสูงกว่าที่ต้องการ
  • ค้นหาค่าตัวเลขจริงด้วย/QJ(อย่างมีประสิทธิภาพ)
  • พิมพ์ค่านั้นด้วยpแทนที่จะพิมพ์ค่าเริ่มต้นของ Pyth เพื่อหลีกเลี่ยงการขึ้นบรรทัดใหม่

การวนซ้ำนี้จะทำซ้ำจนกว่าJจะกลายเป็นศูนย์ ณ จุดที่ข้อผิดพลาดหารด้วยศูนย์จะถูกโยนทิ้งและการวนซ้ำจะสิ้นสุดลง


8

ES6, 105 ไบต์

f=n=>{for(o=0;n--;c?o+=Math.pow(3,s.length-c):o++)s=t(o),c=s.search(2)+1;return t(o);},t=a=>a.toString(3)

การใช้งานคือ: f(1048576)=> `" 10000000000000000001 "

ทดสอบอาร์กิวเมนต์สุดท้ายด้วยความกลัวของคุณเอง ฉันยอมแพ้หลังจาก 5 วินาที

และพิมพ์สวยด้วยความคิดเห็น!

f=n=>{ //define function f with input of n (iteration)
    for(o=0; //define o (output value in decimal)
        n--; //decrement n (goes towards falsy 0) each loop until 0
        c?o+=Math.pow(3,s.length-c):o++) //if search finds a 2, increment output by 3^place (basically moves the 2 to the left and sets the place to 0), else ++
        s=t(o), //convert output to base 3      
        c=s.search(2)+1; //find the location of 2, +1, so a not-found becomes falsy 0.
    return t(o); //return the output in base 3
},

t=a=>a.toString(3);  //convert input a to base 3

5
Btw, f=ฟังก์ชั่นที่ไม่มีชื่อเป็นที่ยอมรับอย่างสมบูรณ์แบบเพื่อให้คุณไม่จำเป็นต้อง
Martin Ender

2
-16 ไบต์:f=n=>{for(o=0;~n--;o+=c?Math.pow(3,s.length+c):1)s=o.toString(3),c=~s.search(2);return s}
ขีดล่าง

@nderscore สวยเท่ห์: D
เข็มทิศ

1
ไบต์ -7 ถ้าคุณใช้ ES7: แทนที่ด้วยMath.pow(3,s.length+c) 3**(s.length+c)
Gustavo Rodrigues

3
@GustavoRodrigues ฉันยังเรียน ES6 ไม่เสร็จ! @ _ @
เข็มทิศ

7

เรติน่า, 55 ไบต์

^
0a
(+`12(.*a)1
20$1
0?2(.*a)1
10$1
0a1
1a
)`1a1
2a
a
<empty line>

ใช้อินพุตเป็น unary

แต่ละบรรทัดควรไปที่ไฟล์ของตัวเอง แต่คุณสามารถเรียกใช้รหัสเป็นไฟล์เดียวกับการ-sตั้งค่าสถานะ เช่น:

> echo 11111|retina -s skew
12

วิธีการ: รัน incrementation 0ในจำนวนครั้งการป้อนข้อมูลสตริงเริ่มต้นจากสตริง

เราใช้กฎการเพิ่มต่อไปนี้:

  • หากมี2: ^2 -> ^12; 02 -> 12;12 -> 20
  • หากไม่มี2: 0$ -> 1$;1$ -> 2$

(มีอย่างน้อยหนึ่งรายการ2ในสตริง^และ$ทำเครื่องหมายจุดเริ่มต้นและจุดสิ้นสุดของสตริงในกฎ)

ข้อมูลเพิ่มเติมเกี่ยวกับจอประสาทตา


7

Java, 154 148

n->{String s="0";for(;n-->0;)s=s.contains("2")?s.replaceAll("(^|0)2","10").replace("12","20"):s.replaceAll("1$","2").replaceAll("0$","1");return s;}

คำตอบนี้อยู่ในรูปแบบของฟังก์ชั่นที่ไม่ระบุชื่อเดียวที่รับอาร์กิวเมนต์จำนวนเต็มและส่งคืนคำตอบเป็นสตริง ด้านล่างนี้เป็นคลาสที่สมบูรณ์สำหรับการทดสอบโซลูชันนี้

import java.util.function.Function;
public class Skew {
    public static void main(String[] args){
        Function<Integer,String> skew = n->{String s="0";for(;n-->0;)s=s.contains("2")?s.replaceAll("(^|0)2","10").replace("12","20"):s.replaceAll("1$","2").replaceAll("0$","1");return s;};

        for(String s:args){
            System.out.println(skew.apply(Integer.parseInt(s)));
        }
    }
}


5

Java, 337 335 253 246 244 ไบต์

เมธอดที่รับค่าดัชนีเป็นlongและส่งคืนผลลัพธ์เป็นสตริง

ใช้longสำหรับดัชนีเพื่อให้สามารถทางทฤษฎีจัดการกับกรณีการทดสอบที่ผ่านมา แต่ผมจริงๆจะไม่แนะนำ

String f(long i){List<Long>l=new ArrayList<>();l.add(0L);for(;i-->0;){int j=l.indexOf(2);if(j!=-1){l.set(j,0L);if(j==0){l.add(0,1L);}else{l.set(j-1,l.get(j-1)+1);}}else{j=l.size()-1;l.set(j,l.get(j)+1);}}String s="";for(long q:l)s+=q;return s;}

4
คุณสามารถย่อให้สั้นลงได้นิดหน่อยโดยทำให้เป็นฟังก์ชั่นแทนโปรแกรมเต็มรูปแบบ (และรับอินพุตเป็นอาร์กิวเมนต์แทนจากสแกนเนอร์)
Geobits

2
คุณไม่ต้องการวงเล็บปีกกาในif(j == 0) คำสั่ง (สี่ไบต์) คุณไม่จำเป็นต้องประกาศk; คุณสามารถใช้jอีกครั้ง (อีกสี่) คุณสามารถใช้การอนุมานประเภททั่วไป (ใน Java 7) ในการประกาศรายการของคุณ ( new ArrayList<>();) (อีก 4)
durron597

4

Haskell, 73 72

ขอบคุณ @nimi สำหรับ 1 ไบต์!

ทางออกนี้จะไม่ชนะรางวัลใด ๆ การทดสอบสองครั้งสุดท้ายใช้เวลาไม่มากนักในการวิ่ง แต่ฉันคิดว่าฉันเล่นกอล์ฟได้ค่อนข้างดี

i(2:b)=1:0:b
i[b]=[b+1]
i(b:2:c)=b+1:0:c
i(b:c)=b:i c
s=(iterate i[0]!!)

วิธีนี้เป็นวิธีที่ค่อนข้างไร้เดียงสาที่คำนวณเลขฐานสองเอียงnโดยเพิ่ม 0 nครั้ง


4

CJam, 24 ไบต์

Q{0\+2a/())+a\+0a*}ri*si

นี่เป็นวิธีO (n log n)โดยที่nคืออินพุต มันเริ่มต้นด้วยการเป็นตัวแทนเอียงไบนารีของ0และเพิ่มจำนวนเต็มที่สอดคล้องกันnครั้ง

ลองใช้ออนไลน์ในล่าม CJam

พื้นหลัง

การเพิ่มตัวเลขในไบนารี่เบ้สามารถทำได้โดยทำตามสองขั้นตอนง่าย ๆ :

  1. แทนที่ในที่สุด2โดย0

  2. หากมีการแทนที่2ให้เพิ่มตัวเลขไปทางซ้าย

    มิฉะนั้นเพิ่มหลักสุดท้าย

มันทำงานอย่างไร

Q     e# Push an empty array.
{     e# Define an anonymous function:
  0\+ e#   Prepend a 0 to the array.
  2a/ e#   Split the array at 2's.
  (   e#   Shift out the first chunk of this array.
  )   e#   Pop the last digit.
  )+  e#   Increment it and append it to the array.
  a\+ e#   Prepend the chunk to the array of chunks.
  0a* e#   Join the chunks, using [0] as separator.
      e#   If there was a 2, it will get replaced with a 0. Otherewise, there's
      e#   only one chunk and joining the array dumps the chunk on the stack.
}     e#
ri*   e# Call the function int(input()) times.
si    e# Cast to string, then to integer. This eliminates leading 0's.

4

VBA, 209 147 142 ไบต์

Sub p(k)
For i=1To k
a=StrReverse(q)
If Left(Replace(a,"0",""),1)=2Then:q=q-2*10^(InStr(a,2)-1)+10^InStr(a,2):Else:q=q+1
Next
msgbox q
End Sub

คณิตศาสตร์ของฉันไม่มีประสิทธิภาพและกอล์ฟของฉันสามารถใช้งานได้ แต่มันเป็นความพยายามครั้งแรกของฉันที่ PoG และคิดว่าฉันจะลองทำสิ่งนี้ เรียงลำดับจากวิธีการ Brute Force แม้ว่า

มันแค่นับด้วย 1 เว้นแต่ว่าเลขตัวสุดท้ายคือ 2 จากนั้นถอยกลับทีละ 2 แล้วกระโดดไปข้างหน้า 10 บวกกับ 0 ต่อท้าย

สิ่งนี้หยุดทำงานที่ 65534 เพราะ VBA ยืนยันที่จะให้ผลลัพธ์ในรูปแบบทางวิทยาศาสตร์ แต่ตรรกะควรทำงานได้ดีสำหรับตัวเลขที่สูงขึ้น

รอคอยที่จะให้คำแนะนำเกี่ยวกับการเล่นกอล์ฟ VBA นั้นไม่ค่อยเป็นมิตรกับกอล์ฟ แต่มักจะไม่ได้นำเสนอและฉันคิดว่ามันสามารถเอาชนะ Java ได้นาน

แก้ไข 1: ขอบคุณมนูที่ช่วยโกน 62 ไบต์

Edit2: สลับdebug.printสำหรับmsgboxเอาท์พุท บันทึก 5 ไบต์


1
คุณสามารถลบเครื่องหมายวงเล็บออกDebug.Print (q)ได้ นอกจากนี้คุณสามารถลบช่องว่างส่วนใหญ่ได้ (ตัวแก้ไขจะนำพวกเขากลับมา แต่ไม่จำเป็น) คุณไม่จำเป็นต้องประกาศเพียงแค่เขียนk as Long kมันจะเป็นตัวแปรประเภท Variant และรหัสจะยังคงใช้งานได้ ด้วยเคล็ดลับเหล่านี้คุณควรลงไปที่ ~ 165 ไบต์
CommonGuy

ความคิดเพิ่มเติม: คุณสามารถละทิ้งอาร์กิวเมนต์แรกและสุดท้ายของInStrพวกเขาเป็นตัวเลือก Trim()ไม่จำเป็นเนื่องจากคุณไม่มีช่องว่าง ใช้อย่างถูกต้องฉันได้รับการ 147 ไบต์
CommonGuy

1
ขอขอบคุณสำหรับความช่วยเหลือมนูคำถามด่วนหนึ่งข้อเอาต์พุตควรเป็นเอาต์พุตมาตรฐาน ฉันไม่แน่ใจว่าจะเป็นอะไรใน VBA debug.print qจะออกมาตรฐานหรือไม่ msgbox qสั้นลง แต่ดูเหมือนว่าจะไม่ได้มาตรฐานเอาท์พุท Sheet1.cells(1,1)ดูเหมือนว่าเอาต์พุตทั่วไปแต่จะถือว่าทำงานใน excel ฉันแค่ไม่แน่ใจว่ารหัสกอล์ฟที่เข้มงวดเป็นอย่างไรเกี่ยวกับสิ่งเหล่านี้
JimmyJazzx

ขอแสดงความยินดีคุณได้คำตอบ java;) ฉันไม่รู้เหมือนกัน ... แค่ใช้MsgBoxถ้ามีคนบ่นคุณก็ยังสามารถเปลี่ยนได้
CommonGuy

4

Javascript ES6, 99 86 78 76 72 ตัวอักษร

f=n=>{for(s="1";--n;s=s.replace(/.?2|.$/,m=>[1,2,10][+m]||20));return s}

// Old version, 76 chars:
f=n=>{for(s="1";--n;s=s.replace(/02|12|2|.$/,m=>[1,2,10][+m]||20));return s}

// Old version, 86 chars:
f=n=>{for(s="1";--n;s=s.replace(/(02|12|2|.$)/,m=>[1,2,10,,,,,,,,,,20][+m]));return s}

// Old version, 99 chars:
f=n=>{for(s="1";--n;s=s.replace(/(^2|02|12|20|.$)/,m=>({0:1,1:2,2:10,12:20,20:100}[+m])));return s}

ทดสอบ:

;[1,2,3,6,7,50,100,200,1000,10000,100000,1000000,1048576].map(f) == "1,2,10,20,100,11011,110020,1100110,111110120,1001110001012,1100001101010020,1111010000100100100,10000000000000000001"

สนุกจริง:มีบุญบางอย่างในระบบตัวเลขนี้ เมื่อเพิ่มตัวเลขคุณจะเปลี่ยนตัวเลขที่อยู่ติดกันสูงสุดสองหลักเสมอ - คุณจะไม่ต้องเปลี่ยนตัวเลขทั้งหมด ด้วยการเป็นตัวแทนที่ถูกต้องที่ช่วยให้การเพิ่มขึ้นใน O (1)

ขอบคุณสำหรับความจริง - มันเป็นฐานของการแก้ปัญหาของฉัน :)


ฉันจะปล่อยวงเล็บปีกกาที่ไม่จำเป็นใน regex ได้อย่างไร o_O
Qwertiy

3

ระดับเสียงคู่, 107 101 ไบต์

ควรเป็นO (log n)หากฉันพบสิทธิ์นี้ ...

function r=s(n)r="";for(a=2.^(uint64(fix(log2(n+1))):-1:1)-1)x=idivide(n,a);r=[r x+48];n-=x*a;end;end

พริตตี้พิมพ์:

function r=s(n)
  r="";
  for(a=2.^(uint64(fix(log2(n+1))):-1:1)-1)
    x=idivide(n,a);
    r=[r x+48];
    n-=x*a;
  end
end

ฉันค่อนข้างจะจัดการกับความท้าทายครั้งสุดท้ายเนื่องจาก Octave จะถือว่าทุกอย่างเป็นตัวเลขทศนิยมและฉันไม่มีความแม่นยำที่จำเป็นในการคำนวณสุดท้าย ฉันได้รอบนั้นโดยใช้ไบต์ที่มีค่าเพื่อบังคับให้ทุกอย่างเป็นจำนวนเต็มไม่ได้ลงนาม ผลลัพธ์ของรายการสุดท้ายมีขนาดใหญ่เกินไปที่จะถือว่าเป็นตัวเลขดังนั้นผลลัพธ์จึงเป็นสตริง

เอาต์พุต (ฉันกำลัง1e18 - 1แสดงให้เห็นว่าฉันสามารถทำได้อย่างถูกต้องและชุดสุดท้ายของผลลัพธ์แสดงระยะเวลาที่ใช้ในการคำนวณค่านั้น):

octave:83> s(uint64(1e18))
ans = 11011110000010110110101100111010011101100100000000000001102

octave:84> s(uint64(1e18)-1)
ans = 11011110000010110110101100111010011101100100000000000001101

octave:85> tic();s(uint64(1e18)-1);toc()
Elapsed time is 0.0270021 seconds.

3

T-SQL, 221 189 177 ไบต์

แก้ไข: รหัสต้นฉบับของรุ่นนี้จะสร้างผลลัพธ์ที่ไม่ถูกต้องสำหรับตัวเลขบางตัวซึ่งได้รับการแก้ไขแล้ว

ในทุกการค้นหาที่นี่เพียงเพิ่มหมายเลขเพื่อคำนวณก่อนเครื่องหมายจุลภาคแรก

ทุกคนรู้ว่า T-SQL เป็นภาษากอล์ฟที่ดีที่สุด นี่คือรุ่นที่จะคำนวณแม้แต่กรณีทดสอบครั้งสุดท้าย บนเครื่องที่ฉันทดสอบมันวิ่งเข้าไปภายในเสี้ยววินาทีฉันสนใจที่จะดูว่ามันทำงานให้คนอื่นได้อย่างไร

DECLARE @ BIGINT=,@T VARCHAR(MAX)='';WITH M AS(SELECT CAST(2AS BIGINT)I UNION ALL SELECT I*2FROM M WHERE I<@)SELECT @T += STR(@/(I-1),1),@%=(I-1)FROM M ORDER BY I DESC SELECT @T

และนี่เป็นอีกครั้ง แต่อ่านได้:

DECLARE 
    @ BIGINT=,
    @T VARCHAR(MAX)='';

WITH M AS
(
    SELECT
        CAST(2 AS BIGINT) I

    UNION ALL

    SELECT I * 2
    FROM M
    WHERE I < @
)

SELECT 
    @T+=STR(@/(I-1),1),
    @%=(I-1)
FROM M 
ORDER BY I DESC

SELECT @T

หากฉันใช้ ints เพียงอย่างเดียวอาจสั้นกว่านี้เล็กน้อยที่ 157 ไบต์:

DECLARE @ INT=,@T VARCHAR(MAX)='';WITH M AS(SELECT 2I UNION ALL SELECT I*2FROM M WHERE I<@)SELECT @T+=STR(@/(I-1),1),@%=(I-1)FROM M ORDER BY I DESC SELECT @T

และอีกครั้งอ่านได้มากขึ้น:

DECLARE 
    @ INT=,
    @T VARCHAR(MAX)='';

WITH M AS
(
    SELECT
        2I

    UNION ALL

    SELECT 
        I * 2
    FROM M
    WHERE I < @
)

SELECT 
    @T+=STR(@/(I-1),1),
    @%=(I-1)
FROM M 
ORDER BY I DESC

SELECT @T

จำไว้ว่า@เป็นตัวระบุที่ถูกต้องใน sql และคุณมักจะได้รับChar(8000) ซึ่งยังคงถูกกว่า nvarchar (สูงสุด) คุณยังสามารถแปลงcharเป็นvarcharหรือใช้strฟังก์ชันได้
Michael B

@MichaelB โอ้ฉันคิดว่าฉันได้ใช้@ฉันโง่ CHAR(8000)คำแนะนำที่ดีงามผมจะพยายามที่ ฉันมักจะลืมเกี่ยวกับการมีอยู่ของการSTR()ขอบคุณสำหรับหัวขึ้น
PenutReaper

ไม่ได้ช่วยจริงๆ อย่างไรก็ตามคุณสามารถเขียนส่วนหลัง CTE ลงใน :: select @t=concat(@t,@/i)ที่ควรมีขนาดเล็กลง ต้องใช้ sql2012
Michael B

@MichaelB อ่า CONCATฉันอยู่ปี 2008 ดังนั้นฉันไม่สามารถทดสอบได้โดยไม่ต้องใช้ซอ SQL ตอนนี้ โทรดีแม้ว่า
PenutReaper

3

รหัสเครื่องจักรทัวริง, 333 293 ไบต์

ฉันใช้การเข้ารหัสที่ใช้ที่นี่

เครื่องนี้ใช้ 9 สถานะและ 11 สี

หากอนุญาตให้ป้อนข้อมูลแบบไบนารีสามารถลดลงได้เพียง 4 สีซึ่งช่วยประหยัดสองสามไบต์ในกระบวนการ

0 _ _ l 1
0 * * r 0
1 9 8 l 2 
1 8 7 l 2
1 7 6 l 2
1 6 5 l 2
1 5 4 l 2
1 4 3 l 2
1 3 2 l 2
1 2 1 l 2
1 1 0 l 2
1 0 9 l 1
1 _ _ r 8
2 _ _ l 3
2 * * l 2
3 _ 1 r 4
3 * * l 5
4 _ _ r 0
4 * * r 4
5 * * l 5
5 _ _ r 6
6 _ _ l 7
6 2 0 l 7
6 * * r 6
7 _ 1 r 4
7 0 1 r 4
7 1 2 r 4
8 _ _ * halt
8 * _ r 8

หากลิงก์ด้านบนใช้งานไม่ได้ (บางครั้งใช้งานได้สำหรับฉันบางครั้งหน้าเว็บปฏิเสธที่จะโหลด) คุณสามารถทดสอบได้โดยใช้การใช้จาวานี้


2

Perl, 66 ไบต์

หมายเลขจะถูกป้อนผ่าน STDIN

$_=1;$c=<>;s/(.*)(.?)2(.*)/$1.$2+1 .$3.0/e||$_++while(--$c);print;

คุณช่วยอธิบายวิธีแก้ปัญหาของคุณได้อย่างไร? ฉันไม่เห็นวิธีการที่คุณต้องการ(.?)ใน$2ตั้งแต่(.*)ใน$1ควรจะโลภและได้รับตัวละครที่แรก แต่ถ้ามันถูกลบออกรหัสไม่ได้ผลลัพธ์ที่ถูกต้องอีกต่อไป! ;โดยวิธีการที่คุณไม่จำเป็นต้องสุดท้าย
CJ Dennis

@CJDennis ขอบคุณสำหรับการบันทึกไบต์นั้น อย่างไรก็ตาม. จะได้รับตัวเลขมาทางขวาก่อนหน้าทั้งสองยกเว้นว่าไม่มีตัวเลขอยู่ที่นั่น (เช่น 20) ในกรณีเช่น 120 หรือ 10020 กลุ่ม regex เช่นนี้: () (1) 2 (0) และ (10) (0) 2 (0) จากนั้นกลุ่มแรกจะถูกละเว้นเพียงแค่กลุ่มที่สอง (ซึ่งเป็นหนึ่งหลักเสมอถ้าเป็นไปได้หรือว่างเปล่า) จะเพิ่มขึ้นและกลุ่มที่สาม (ประกอบด้วยเลขศูนย์เสมอ) จะถูกละเว้นและเพิ่มศูนย์ ฉันเพียงแค่ใช้รายการ OEIS เป็นแนวทางของฉันสำหรับ regex นี้
frederick

ผมได้รหัสของคุณลงไป 53 $c=<>;s/(.*)2(.*)/$1+1 .$2.0/e||$_++while($c--);printไบต์: ฉันพูดถูก(.?)ไม่เคยจับอะไรเลย
CJ Dennis

สามารถปรับให้เหมาะกับ$_=1;$c=<>;s/(.?)2/1+$1.0/e||$_++while(--$c);printซึ่งเป็น 50 ไบต์ .*ที่จุดเริ่มต้นหรือจุดสิ้นสุดสามารถเพิ่มประสิทธิภาพออกไปถ้าคุณเพียงแค่แทนที่ด้วยข้อความต้นฉบับ นอกจากนี้ยังไม่มีเหตุผลที่จะเพิ่ม 0 ในตอนท้ายเนื่องจากมีเลขศูนย์ในต้นฉบับ$3เสมอ
Thraidh

2

Pyth, 19 ไบต์

m/=%Qtydtd^L2_SslhQ

ความซับซ้อนของลอการิทึม เสร็จสิ้นได้อย่างง่ายดายในเวลาที่จำเป็น เอาท์พุทในรูปแบบของรายการของตัวเลข

การสาธิต


2

Perl, 84 70 67 ไบต์

$n=<>;$d*=2while($d++<$n);$_.=int($n/$d)while($n%=$d--,$d/=2);print

ไม่ค่อยเล่นกอล์ฟเริ่มดีขึ้น แต่ใช้งานได้เร็วมาก!

ข้อเสนอแนะของ Dennis ทำให้มันลดลงเหลือ 51 (สวิตช์ 50 ไบต์ + -p)

$d*=2while$d++<$_;$\.=$_/$d|0while$_%=$d--,$d/=2}{

มันจะต้องถูกเรียกเหมือนperl -p skew_binary.pl num_list.txtที่num_list.txtมีบรรทัดเดียวที่มีหมายเลขที่จะเข้ารหัสมัน


@ เฟรเดอริกอยู่ที่ขอบที่นั่งรอ 2
Robert Grant

@RobertGrant เขาแสดงความคิดเห็นของเขาจากสองสิ่งเป็นสิ่งเดียว!
CJ Dennis

สองสิ่ง: 1. แทนที่จะใช้ $ ARGV [0] ให้ใช้ <> เป็นอินพุต มันจะรับอินพุตจาก stdin เว้นแต่ว่ามีไฟล์ใด ๆ เป็นอาร์กิวเมนต์ 2. สำหรับแผนการนับแปลก ๆ เช่นนี้ให้ใช้นิพจน์ทั่วไป แทนที่จะทำการดำเนินการทางคณิตศาสตร์คี่คุณสามารถแทนที่ตัวเลขในตัวเลขราวกับว่ามันเป็นสตริง ส่วนที่ดีที่สุดคือคุณสามารถใช้การดำเนินการทางคณิตศาสตร์ (เช่นการเพิ่มขึ้น) ในเวลาเดียวกันโดยมีเงื่อนไขว่าเป็นสตริงที่ประกอบด้วยตัวเลขทั้งหมด ตรวจสอบเอกสารประกอบของตัวดำเนินการนิพจน์ทั่วไปเนื่องจากพวกมันมีประโยชน์มากในหลายโอกาส
frederick

ขออภัยฉันกด Enter และบันทึกไว้ก่อนที่ความคิดเห็นจะเสร็จสิ้น
frederick

@ เฟรดเดอริกไม่เจียมเนื้อเจียมตัว เรารู้ว่าเกิดอะไรขึ้น!
Robert Grant

1

Mathematica, 65

ควรจะค่อนข้างเร็วพอถึงแม้ว่าฉันต้องยอมรับว่าฉันแอบมองสิ่งอื่น ๆ ก่อนที่จะทำสิ่งนี้

f = (n = #;
     l = 0; 
     While[n > 0,
      m = Floor[Log2[1 + n]];
      l += 10^(m - 1);
      n -= 2^m - 1
     ]; l)&

การใช้งาน:

f[1000000000000000000]

เอาท์พุท:

11011110000010110110101100111010011101100100000000000001102

เริ่มต้นให้ข้อความแสดงข้อผิดพลาด MaxExtraPrecision ที่ไหนสักแห่งที่ผ่านมา 10 ^ 228 (ซึ่งจะคำนวณผลลัพธ์ใน. 03 วินาทีบนเครื่องของฉัน)

หลังจากลบขีด จำกัด MaxExtraPrecision มันจะจัดการตัวเลขได้สูงสุดประมาณ 10 ^ 8000 ในหนึ่งวินาที

การป้อนข้อมูล:

Timing[Block[{$MaxExtraPrecision = Infinity}, f[10^8000]];]

เอาท์พุท:

{1.060807, Null}

1

C, 95 ไบต์

void f(unsigned long i,int*b){for(unsigned long a=~0,m=0;a;a/=2,b+=!!m)m|=*b=i/a,i-=a**b;*b=3;}

สิ่งนี้ยอมรับจำนวนเต็มและบัฟเฟอร์ที่ส่งคืนตัวเลข ผลลัพธ์จะถูกเก็บไว้ในbสิ้นสุดด้วยค่า3(ซึ่งไม่สามารถเกิดขึ้นได้ในผลลัพธ์) เราไม่ต้องจัดการอินพุต0(ตามคำถามที่ระบุเฉพาะจำนวนเต็มบวก) ดังนั้นจึงไม่มีเคสพิเศษเพื่อหลีกเลี่ยงเอาต์พุตว่าง

รหัสขยาย

void f(unsigned long i,int*b)
{
    for (unsigned long a=~0, m=0;  a;  a/=2, b+=(m!=0)) {
        *b = i/a;               /* rounds down */
        i -= *b * a;
        m = m | *b;             /* m != 0 after leading zeros */
    }
    *b=3;                       /* add terminator */
}

เราดำเนินการโดยการลบอย่างต่อเนื่องโดยเริ่มจากหลักสำคัญ ภาวะแทรกซ้อนเดียวคือเราใช้ตัวแปรmเพื่อหลีกเลี่ยงการพิมพ์ศูนย์นำ ส่วนขยายตามธรรมชาติที่unsigned long longอาจเกิดขึ้นหากต้องการในราคา 10 ไบต์

โปรแกรมทดสอบ

หมายเลข Pass ที่จะถูกแปลงเป็นอาร์กิวเมนต์คำสั่ง มันจะแปลงintบัฟเฟอร์อาร์เรย์เป็นสตริงหลักที่พิมพ์ได้ Runtime 1000000000000000000น้อยกว่าหนึ่งมิลลิวินาทีสำหรับการป้อนข้อมูล

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char**argv)
{
    while (*++argv) {
        unsigned long i = strtoul(*argv, NULL, 10);
        int result[1024];
        f(i,result);

        /* convert to string */
        char s[1024];
        {char*d=s;int*p=result;while(*p!=3)*d++=*p+++'0';*d=0;}
        printf("%lu = %s\n", i, s);
    }

    return EXIT_SUCCESS;
}

ผลการทดสอบ

$ ./51517 $(seq 20)
1 = 1
2 = 2
3 = 10
4 = 11
5 = 12
6 = 20
7 = 100
8 = 101
9 = 102
10 = 110
11 = 111
12 = 112
13 = 120
14 = 200
15 = 1000
16 = 1001
17 = 1002
18 = 1010
19 = 1011
20 = 1012

ผมคิดว่ารุ่น C ++ จะคล้ายกัน แต่สามารถใช้auto a=~0ullเป็นข้อได้เปรียบเล็กน้อย ...
Toby Speight


0

CoffeeScript, 92 69 ไบต์

จากคำตอบและการอัพเดทของQwertiy :

f=(n)->s='1';(s=s.replace /(.?2|.$)/,(m)->[1,2,10][+m]||20)while--n;s

# older version, 92 bytes
f=(n)->s='1';(s=s.replace /(^2|02|12|20|.$)/,(m)->{0:1,1:2,2:10,12:20,20:100}[+m])while--n;s

2
การแปลงเป็นภาษาอื่นโดยไม่มีการเพิ่มประสิทธิภาพอย่างง่าย ๆ โดยการลบวงเล็บปีกกาที่ไม่จำเป็นใน regex ดูไม่เจ๋งสำหรับฉัน ...
Qwertiy

@Qwertiy ฉันได้ระบุแหล่งที่มากับคำตอบของคุณและทั้งสองคำตอบฉันไม่สามารถให้ผลลัพธ์เดียวกันโดยไม่ต้องวงเล็บใน regex
rink.attendant.6

เหตุการณ์ทั้งหมดจะถูกแทนที่ ทำไมคุณถึงต้องอยู่ในกลุ่ม? JS เวอร์ชันทำงานใน Firefox โดยไม่ต้องวงเล็บ
Qwertiy

0

Japt , 31 ไบต์

_r/?2|.$/g_÷C ç20 ª°Zs3}}gU['0]

ลองออนไลน์!

เกือบจะเป็นพอร์ตโดยตรงของโซลูชัน JSนี้ ไม่มีความคิดถ้ามีวิธีที่ดีกว่า

เอาออกแล้วมันทำงานอย่างไร

X{Xr/?2|.$/gZ{Z÷C ç20 ||++Zs3}}gU['0]

X{     Declare a function...
Xr       Accept a string, replace the regex...
/?2|.$/g   /.?2|.$/   (g is needed to match *only once*, opposite of JS)
Z{       ...with the function... (matched string will be 0,1,2,02 or 12)
Z÷C        Implicitly cast the matched string into number, divide by 12
ç20        Repeat "20" that many times (discard fractions)
||         If the above results in "", use the next one instead
++Z        Increment the value
s3         Convert to base-3 string (so 0,1,2 becomes 1,2,10)
}}
gU['0] Repeatedly apply the function on "0", U (input) times

0

Stax , 16 ไบต์

üxëàè£öΦGΩ│Je5█ò

เรียกใช้และแก้ไขข้อบกพร่อง

ฉันไม่แน่ใจว่าระดับความซับซ้อนที่เป็นทางการคืออะไร แต่เร็วพอที่จะทำแบบทดสอบทั้งหมดในเวลาสิบวินาทีในเครื่องนี้

คลายกล่อง ungolfed และแสดงความคิดเห็นมันมีลักษณะเช่นนี้ ในโปรแกรมนี้การลงทะเบียน x นั้นมีอินพุตอยู่ แต่เดิม

z       push []
{       start block for while loop
 |X:2N  -log2(++x)
 {^}&   increment array at index (pad with 0s if necessary)
 xc:G-X unset high bit of x; write back to x register
w       while; loop until x is falsy (0)
$       convert to string

เรียกใช้อันนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.